aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2019-03-21 20:42:38 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2019-03-21 20:42:47 +0100
commit6767114285db9d0e16dc278d08f231e8561546b4 (patch)
tree0945902a2242fd7ec0a1f7fd3e6acbb769e723bd /tests/auto/quick
parentee076afedccbe1d37306a7972051f84eb036d655 (diff)
parentc32b109e9dea44c6775c2dbf8f164870c1dc8971 (diff)
Merge remote-tracking branch 'origin/dev' into wip/scenegraphng
Diffstat (limited to 'tests/auto/quick')
-rw-r--r--tests/auto/quick/drawingmodes/tst_drawingmodes.cpp38
-rw-r--r--tests/auto/quick/examples/examples.pro1
-rw-r--r--tests/auto/quick/examples/tst_examples.cpp19
-rw-r--r--tests/auto/quick/geometry/tst_geometry.cpp4
-rw-r--r--tests/auto/quick/nodes/tst_nodestest.cpp19
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST4
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml45
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml122
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml120
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml93
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml70
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml74
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml79
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml161
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml57
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml73
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml79
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/flickableinterop.pro15
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp799
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml109
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml64
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/multipointtoucharea_interop.pro15
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp306
-rw-r--r--tests/auto/quick/pointerhandlers/pointerhandlers.pro13
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml125
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml45
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml124
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml60
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml61
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml66
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/reparenting.qml59
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml111
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro21
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp573
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml164
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/qquickhoverhandler.pro15
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp271
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml77
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml59
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml53
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/qquickpinchhandler.pro16
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp772
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreated.qml34
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreatedInWindow.qml20
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/handlerInWindow.qml14
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/data/singleitem.qml28
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/qquickpointerhandler.pro16
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp685
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml86
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml57
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/qquickpointhandler.pro15
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp346
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml88
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml45
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml45
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml52
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml41
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/qquicktaphandler.pro16
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp721
-rw-r--r--tests/auto/quick/propertyrequirements/propertyrequirements.pro7
-rw-r--r--tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp204
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp82
-rw-r--r--tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp54
-rw-r--r--tests/auto/quick/qquickanimatedsprite/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml38
-rw-r--r--tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro4
-rw-r--r--tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp108
-rw-r--r--tests/auto/quick/qquickanimations/BLACKLIST40
-rw-r--r--tests/auto/quick/qquickanimations/data/finished.qml95
-rw-r--r--tests/auto/quick/qquickanimations/data/replacingTransitions.qml51
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp188
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp62
-rw-r--r--tests/auto/quick/qquickbehaviors/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml11
-rw-r--r--tests/auto/quick/qquickbehaviors/data/aliased.qml1
-rw-r--r--tests/auto/quick/qquickbehaviors/data/oneway.qml20
-rw-r--r--tests/auto/quick/qquickbehaviors/data/overwrittenbehavior.qml14
-rw-r--r--tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml16
-rw-r--r--tests/auto/quick/qquickbehaviors/qquickbehaviors.pro2
-rw-r--r--tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp64
-rw-r--r--tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp38
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml4
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml446
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml4
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml86
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_line.qml91
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml35
-rw-r--r--tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro5
-rw-r--r--tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp27
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/Component01.qml51
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/Component02.qml24
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/TestComponent.qml4
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/componentTest.qml33
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/test.qml4
-rw-r--r--tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro6
-rw-r--r--tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp120
-rw-r--r--tests/auto/quick/qquickdrag/tst_qquickdrag.cpp88
-rw-r--r--tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp133
-rw-r--r--tests/auto/quick/qquickflickable/BLACKLIST21
-rw-r--r--tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml3
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp266
-rw-r--r--tests/auto/quick/qquickflipable/tst_qquickflipable.cpp20
-rw-r--r--tests/auto/quick/qquickfocusscope/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp66
-rw-r--r--tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp18
-rw-r--r--tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp2
-rw-r--r--tests/auto/quick/qquickframebufferobject/BLACKLIST4
-rw-r--r--tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp8
-rw-r--r--tests/auto/quick/qquickgridview/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickgridview/data/attachedProperties.qml16
-rw-r--r--tests/auto/quick/qquickgridview/data/margins2.qml80
-rw-r--r--tests/auto/quick/qquickgridview/data/mirroring.qml9
-rw-r--r--tests/auto/quick/qquickgridview/data/qtbug49218.qml126
-rw-r--r--tests/auto/quick/qquickgridview/data/qtbug57225.qml95
-rw-r--r--tests/auto/quick/qquickgridview/data/releaseItems.qml12
-rw-r--r--tests/auto/quick/qquickgridview/data/unrequestedItems.qml3
-rw-r--r--tests/auto/quick/qquickgridview/qquickgridview.pro2
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp639
-rw-r--r--tests/auto/quick/qquickimage/data/car.ktxbin0 -> 11908 bytes
-rw-r--r--tests/auto/quick/qquickimage/data/logo.pkmbin0 -> 32784 bytes
-rw-r--r--tests/auto/quick/qquickimage/data/pattern.pkmbin0 -> 2064 bytes
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp107
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp101
-rw-r--r--tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml59
-rw-r--r--tests/auto/quick/qquickitem/qquickitem.pro5
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp217
-rw-r--r--tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop.qml13
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinates.qml17
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp161
-rw-r--r--tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp100
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml16
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml14
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml17
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml14
-rw-r--r--tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml78
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml131
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST3
-rw-r--r--tests/auto/quick/qquicklistview/data/addoncompleted.qml90
-rw-r--r--tests/auto/quick/qquicklistview/data/appendDuringScrollDown.qml28
-rw-r--r--tests/auto/quick/qquicklistview/data/attachedProperties.qml16
-rw-r--r--tests/auto/quick/qquicklistview/data/flickBothDirections.qml15
-rw-r--r--tests/auto/quick/qquicklistview/data/itemlist-flicker.qml11
-rw-r--r--tests/auto/quick/qquicklistview/data/itemlist.qml11
-rw-r--r--tests/auto/quick/qquicklistview/data/listview-itematindex.qml15
-rw-r--r--tests/auto/quick/qquicklistview/data/listview-sections-package.qml3
-rw-r--r--tests/auto/quick/qquicklistview/data/listviewtest-package.qml3
-rw-r--r--tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml16
-rw-r--r--tests/auto/quick/qquicklistview/data/programmaticFlickAtBounds3.qml19
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug34576.qml102
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml125
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug63974.qml34
-rw-r--r--tests/auto/quick/qquicklistview/data/releaseItems.qml12
-rw-r--r--tests/auto/quick/qquicklistview/data/repositionResizedDelegate.qml3
-rw-r--r--tests/auto/quick/qquicklistview/data/rightToLeft.qml9
-rw-r--r--tests/auto/quick/qquicklistview/data/roundingErrors.qml16
-rw-r--r--tests/auto/quick/qquicklistview/data/sectionSnapping.qml49
-rw-r--r--tests/auto/quick/qquicklistview/data/setpositiononlayout.qml87
-rw-r--r--tests/auto/quick/qquicklistview/data/sizeTransitions.qml16
-rw-r--r--tests/auto/quick/qquicklistview/data/snapOneItemWrongDirection.qml18
-rw-r--r--tests/auto/quick/qquicklistview/data/snapToItemWithSpacing.qml18
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml16
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml16
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml16
-rw-r--r--tests/auto/quick/qquicklistview/data/strictlyenforcerange-resize.qml31
-rw-r--r--tests/auto/quick/qquicklistview/data/unrequestedItems.qml3
-rw-r--r--tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml63
-rw-r--r--tests/auto/quick/qquicklistview/qquicklistview.pro3
-rw-r--r--tests/auto/quick/qquicklistview/randomsortmodel.cpp5
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp1208
-rw-r--r--tests/auto/quick/qquickloader/BLACKLIST4
-rw-r--r--tests/auto/quick/qquickloader/data/bindings.qml71
-rw-r--r--tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml27
-rw-r--r--tests/auto/quick/qquickloader/data/itemLoaderWindow.qml22
-rw-r--r--tests/auto/quick/qquickloader/data/parentErrors.qml47
-rw-r--r--tests/auto/quick/qquickloader/data/rootContext.qml55
-rw-r--r--tests/auto/quick/qquickloader/qquickloader.pro2
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp619
-rw-r--r--tests/auto/quick/qquickmousearea/data/mask.qml63
-rw-r--r--tests/auto/quick/qquickmousearea/data/nestedSendEvent.qml49
-rw-r--r--tests/auto/quick/qquickmousearea/data/twoMouseAreas.qml33
-rw-r--r--tests/auto/quick/qquickmousearea/qquickmousearea.pro2
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp785
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml9
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml40
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp159
-rw-r--r--tests/auto/quick/qquickopenglinfo/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickpainteditem/BLACKLIST27
-rw-r--r--tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp4
-rw-r--r--tests/auto/quick/qquickpath/data/anglearc.qml12
-rw-r--r--tests/auto/quick/qquickpath/tst_qquickpath.cpp58
-rw-r--r--tests/auto/quick/qquickpathview/data/flickableDelegate.qml16
-rw-r--r--tests/auto/quick/qquickpathview/data/nestedInFlickable.qml16
-rw-r--r--tests/auto/quick/qquickpathview/data/objectModelMove.qml123
-rw-r--r--tests/auto/quick/qquickpathview/data/panels.qml3
-rw-r--r--tests/auto/quick/qquickpathview/data/pathview_package.qml3
-rw-r--r--tests/auto/quick/qquickpathview/data/qtbug37815.qml14
-rw-r--r--tests/auto/quick/qquickpathview/data/qtbug53464.qml14
-rw-r--r--tests/auto/quick/qquickpathview/data/removePath.qml2
-rw-r--r--tests/auto/quick/qquickpathview/data/treemodel.qml3
-rw-r--r--tests/auto/quick/qquickpathview/data/vdm.qml3
-rw-r--r--tests/auto/quick/qquickpathview/qquickpathview.pro2
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp271
-rw-r--r--tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp62
-rw-r--r--tests/auto/quick/qquickpixmapcache/qquickpixmapcache.pro1
-rw-r--r--tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp6
-rw-r--r--tests/auto/quick/qquickpositioners/qquickpositioners.pro2
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp431
-rw-r--r--tests/auto/quick/qquickrectangle/data/gradient-preset.qml16
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp32
-rw-r--r--tests/auto/quick/qquickrepeater/data/asynchronousMove.qml51
-rw-r--r--tests/auto/quick/qquickrepeater/data/itemlist.qml17
-rw-r--r--tests/auto/quick/qquickrepeater/data/ownership.qml4
-rw-r--r--tests/auto/quick/qquickrepeater/data/package.qml35
-rw-r--r--tests/auto/quick/qquickrepeater/data/visualitemmodel.qml3
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp167
-rw-r--r--tests/auto/quick/qquickshadereffect/data/MyIcon.qml14
-rw-r--r--tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml14
-rw-r--r--tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp30
-rw-r--r--tests/auto/quick/qquickshape/BLACKLIST8
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem5.pngbin0 -> 9377 bytes
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem5.qml37
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem6.pngbin0 -> 11024 bytes
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem6.qml35
-rw-r--r--tests/auto/quick/qquickshape/qquickshape.pro24
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp76
-rw-r--r--tests/auto/quick/qquickshortcut/BLACKLIST7
-rw-r--r--tests/auto/quick/qquickshortcut/data/shortcutsRect.qml54
-rw-r--r--tests/auto/quick/qquickshortcut/qquickshortcut.pro3
-rw-r--r--tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp124
-rw-r--r--tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp8
-rw-r--r--tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp6
-rw-r--r--tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp12
-rw-r--r--tests/auto/quick/qquickstates/data/duplicateStateName.qml13
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp232
-rw-r--r--tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp16
-rw-r--r--tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp8
-rw-r--r--tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml76
-rw-r--r--tests/auto/quick/qquicktableview/data/asyncloader.qml56
-rw-r--r--tests/auto/quick/qquicktableview/data/asyncplain.qml96
-rw-r--r--tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml97
-rw-r--r--tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml81
-rw-r--r--tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml87
-rw-r--r--tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml94
-rw-r--r--tests/auto/quick/qquicktableview/data/contentwidthheight.qml80
-rw-r--r--tests/auto/quick/qquicktableview/data/countingtableview.qml98
-rw-r--r--tests/auto/quick/qquicktableview/data/delegatewithanchors.qml65
-rw-r--r--tests/auto/quick/qquicktableview/data/forcelayout.qml76
-rw-r--r--tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml85
-rw-r--r--tests/auto/quick/qquicktableview/data/plaintableview.qml86
-rw-r--r--tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml83
-rw-r--r--tests/auto/quick/qquicktableview/data/setcontentpos.qml69
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml61
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewfocus.qml77
-rw-r--r--tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml64
-rw-r--r--tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml64
-rw-r--r--tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml76
-rw-r--r--tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml88
-rw-r--r--tests/auto/quick/qquicktableview/qquicktableview.pro15
-rw-r--r--tests/auto/quick/qquicktableview/testmodel.h165
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp2157
-rw-r--r--tests/auto/quick/qquicktext/data/contentHeight.qml7
-rw-r--r--tests/auto/quick/qquicktext/data/elideParentChanged.qml13
-rw-r--r--tests/auto/quick/qquicktext/data/implicitSizeChangeRewrap.qml27
-rw-r--r--tests/auto/quick/qquicktext/qquicktext.pro3
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp469
-rw-r--r--tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp4
-rw-r--r--tests/auto/quick/qquicktextedit/data/keys_shortcutoverride.qml34
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp357
-rw-r--r--tests/auto/quick/qquicktextinput/BLACKLIST3
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp428
-rw-r--r--tests/auto/quick/qquickview/qquickview.pro1
-rw-r--r--tests/auto/quick/qquickview/tst_qquickview.cpp32
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/create.qml3
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/datalist-package.qml3
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/datalist.qml3
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml65
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/groups-invalid.qml11
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/groups-package.qml27
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/groups.qml27
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/invalidAttachment.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/itemsDestroyed_package.qml3
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties-package.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties-package.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties-package.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/onChanged.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/packageView.qml3
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties-package.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties-package.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties.qml7
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/visualdatamodel.qml3
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp451
-rw-r--r--tests/auto/quick/qquickwindow/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickwindow/data/unloadSubWindow.qml6
-rw-r--r--tests/auto/quick/qquickwindow/data/windowattached.qml1
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp1040
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/empty.xml0
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/get.qml61
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/groups.qml10
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/groups.xml18
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/model.qml11
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/model.xml54
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/model2.xml14
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/propertychanges.qml11
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/proxyCrash.qml9
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/recipes.qml11
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/recipes.xml90
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/roleCrash.qml8
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/roleErrors.qml11
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/roleKeys.qml13
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/testtypes.qml8
-rw-r--r--tests/auto/quick/qquickxmllistmodel/data/unique.qml9
-rw-r--r--tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro16
-rw-r--r--tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp1004
-rw-r--r--tests/auto/quick/quick.pro14
-rw-r--r--tests/auto/quick/rendernode/tst_rendernode.cpp18
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp119
-rw-r--r--tests/auto/quick/shared/geometrytestutil.cpp43
-rw-r--r--tests/auto/quick/shared/geometrytestutil.h49
-rw-r--r--tests/auto/quick/shared/util.pri2
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp46
-rw-r--r--tests/auto/quick/shared/viewtestutil.h11
-rw-r--r--tests/auto/quick/shared/visualtestutil.cpp30
-rw-r--r--tests/auto/quick/shared/visualtestutil.h5
-rw-r--r--tests/auto/quick/sharedimage/tst_sharedimage.cpp2
-rw-r--r--tests/auto/quick/touchmouse/BLACKLIST2
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp301
331 files changed, 22129 insertions, 5238 deletions
diff --git a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
index d4065e3d38..afc66948b0 100644
--- a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
+++ b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp
@@ -51,8 +51,8 @@ public:
view.setResizeMode(QQuickView::SizeViewToRootObject);
view.setSource(testFileUrl(fileName));
view.setVisible(true);
- QTest::qWaitForWindowExposed(&view);
- return view.grabWindow();
+ bool exposed = QTest::qWaitForWindowExposed(&view);
+ return exposed ? view.grabWindow() : QImage();
}
//It is important for platforms that only are able to show fullscreen windows
@@ -149,6 +149,10 @@ void tst_drawingmodes::points()
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
#ifdef Q_OS_WIN
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES)
QSKIP("ANGLE cannot draw GL_POINTS.");
@@ -187,6 +191,11 @@ void tst_drawingmodes::lines()
DrawingModeItem::drawingMode = GL_LINES;
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("DrawingModes.qml");
QCOMPARE(fb.width(), 200);
@@ -213,6 +222,11 @@ void tst_drawingmodes::lineStrip()
DrawingModeItem::drawingMode = GL_LINE_STRIP;
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("DrawingModes.qml");
QCOMPARE(fb.width(), 200);
@@ -241,6 +255,11 @@ void tst_drawingmodes::lineLoop()
DrawingModeItem::drawingMode = GL_LINE_LOOP;
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("DrawingModes.qml");
QCOMPARE(fb.width(), 200);
@@ -269,6 +288,11 @@ void tst_drawingmodes::triangles()
DrawingModeItem::drawingMode = GL_TRIANGLES;
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("DrawingModes.qml");
QCOMPARE(fb.width(), 200);
@@ -293,6 +317,11 @@ void tst_drawingmodes::triangleStrip()
DrawingModeItem::drawingMode = GL_TRIANGLE_STRIP;
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("DrawingModes.qml");
QCOMPARE(fb.width(), 200);
@@ -316,6 +345,11 @@ void tst_drawingmodes::triangleFan()
DrawingModeItem::drawingMode = GL_TRIANGLE_FAN;
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("DrawingModes.qml");
QCOMPARE(fb.width(), 200);
diff --git a/tests/auto/quick/examples/examples.pro b/tests/auto/quick/examples/examples.pro
index fd8cfd83c8..c047f993ea 100644
--- a/tests/auto/quick/examples/examples.pro
+++ b/tests/auto/quick/examples/examples.pro
@@ -8,5 +8,4 @@ DEFINES += SRCDIR=\\\"$$PWD\\\"
#temporary
QT += core-private gui-private qml-private quick-private testlib
-!qtHaveModule(xmlpatterns): DEFINES += QT_NO_XMLPATTERNS
diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp
index d35a2e971a..fdefa855e4 100644
--- a/tests/auto/quick/examples/tst_examples.cpp
+++ b/tests/auto/quick/examples/tst_examples.cpp
@@ -36,7 +36,7 @@
#include <QQmlEngine>
#include <QQmlError>
-static QtMessageHandler testlibMsgHandler = 0;
+static QtMessageHandler testlibMsgHandler = nullptr;
void msgHandlerFilter(QtMsgType type, const QMessageLogContext &ctxt, const QString &msg)
{
if (type == QtCriticalMsg || type == QtFatalMsg)
@@ -74,29 +74,20 @@ tst_examples::tst_examples()
{
// Add files to exclude here
excludedFiles << "snippets/qml/listmodel/listmodel.qml"; //Just a ListModel, no root QQuickItem
- excludedFiles << "examples/quick/demos/photosurface/photosurface.qml"; // root item is Window rather than Item
+ excludedFiles << "snippets/qml/tablemodel/fruit-example-delegatechooser.qml"; // Requires QtQuick.Controls import.
// Add directories you want excluded here
excludedDirs << "shared"; //Not an example
excludedDirs << "snippets/qml/path"; //No root QQuickItem
excludedDirs << "examples/qml/qmlextensionplugins"; //Requires special import search path
- excludedDirs << "examples/quick/tutorials/gettingStartedQml"; //C++ example, but no cpp files in root dir
// These snippets are not expected to run on their own.
excludedDirs << "snippets/qml/visualdatamodel_rootindex";
excludedDirs << "snippets/qml/qtbinding";
excludedDirs << "snippets/qml/imports";
- excludedFiles << "examples/quick/shapes/content/pathitem.qml"; // relies on resources
- excludedFiles << "examples/quick/shapes/content/pathiteminteract.qml"; // relies on resources
-
-#ifdef QT_NO_XMLPATTERNS
- excludedDirs << "demos/twitter";
- excludedDirs << "demos/flickr";
- excludedDirs << "demos/photoviewer";
- excludedFiles << "snippets/qml/xmlrole.qml";
- excludedFiles << "particles/itemparticle/particleview.qml";
- excludedFiles << "views/visualdatamodel/slideshow.qml";
-#endif
+ excludedFiles << "snippets/qml/image-ext.qml";
+ excludedFiles << "examples/quick/shapes/content/main.qml"; // relies on resources
+ excludedFiles << "examples/quick/shapes/content/interactive.qml"; // relies on resources
#if !QT_CONFIG(opengl)
//No support for Particles
diff --git a/tests/auto/quick/geometry/tst_geometry.cpp b/tests/auto/quick/geometry/tst_geometry.cpp
index 904f85c4c6..54de46276c 100644
--- a/tests/auto/quick/geometry/tst_geometry.cpp
+++ b/tests/auto/quick/geometry/tst_geometry.cpp
@@ -58,7 +58,7 @@ void GeometryTest::testPoint2D()
QSGGeometry::updateRectGeometry(&geometry, QRectF(1, 2, 3, 4));
QSGGeometry::Point2D *pts = geometry.vertexDataAsPoint2D();
- QVERIFY(pts != 0);
+ QVERIFY(pts != nullptr);
QCOMPARE(pts[0].x, (float) 1);
QCOMPARE(pts[0].y, (float) 2);
@@ -91,7 +91,7 @@ void GeometryTest::testTexturedPoint2D()
QSGGeometry::updateTexturedRectGeometry(&geometry, QRectF(1, 2, 3, 4), QRectF(5, 6, 7, 8));
QSGGeometry::TexturedPoint2D *pts = geometry.vertexDataAsTexturedPoint2D();
- QVERIFY(pts != 0);
+ QVERIFY(pts != nullptr);
QCOMPARE(pts[0].x, (float) 1);
QCOMPARE(pts[0].y, (float) 2);
diff --git a/tests/auto/quick/nodes/tst_nodestest.cpp b/tests/auto/quick/nodes/tst_nodestest.cpp
index 63e0aeb324..79a9e5f757 100644
--- a/tests/auto/quick/nodes/tst_nodestest.cpp
+++ b/tests/auto/quick/nodes/tst_nodestest.cpp
@@ -41,6 +41,9 @@
#include <QtQuick/qsgsimpletexturenode.h>
#include <QtQuick/private/qsgtexture_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+
QT_BEGIN_NAMESPACE
inline bool operator==(const QSGGeometry::TexturedPoint2D& l, const QSGGeometry::TexturedPoint2D& r)
{
@@ -73,13 +76,16 @@ private Q_SLOTS:
void textureNodeRect();
private:
- QOffscreenSurface *surface;
- QOpenGLContext *context;
- QSGDefaultRenderContext *renderContext;
+ QOffscreenSurface *surface = nullptr;
+ QOpenGLContext *context = nullptr;
+ QSGDefaultRenderContext *renderContext = nullptr;
};
void NodesTest::initTestCase()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL))
+ QSKIP("OpenGL not supported by the platform");
+
QSGRenderLoop *renderLoop = QSGRenderLoop::instance();
surface = new QOffscreenSurface;
@@ -112,8 +118,8 @@ class DummyRenderer : public QSGBatchRenderer::Renderer
public:
DummyRenderer(QSGRootNode *root, QSGDefaultRenderContext *renderContext)
: QSGBatchRenderer::Renderer(renderContext)
- , changedNode(0)
- , changedState(0)
+ , changedNode(nullptr)
+ , changedState(nullptr)
, renderCount(0)
{
setRootNode(root);
@@ -141,9 +147,6 @@ public:
int DummyRenderer::globalRendereringOrder;
NodesTest::NodesTest()
- : surface(Q_NULLPTR)
- , context(Q_NULLPTR)
- , renderContext(Q_NULLPTR)
{
}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
new file mode 100644
index 0000000000..62aa19a9ae
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
@@ -0,0 +1,4 @@
+[touchAndDragHandlerOnFlickable]
+windows gcc
+[touchDragFlickableBehindSlider]
+windows gcc
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
new file mode 100644
index 0000000000..4b2935b52e
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+SequentialAnimation {
+ id: tapFlash
+ running: false
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
new file mode 100644
index 0000000000..7a32170bed
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/GrooveDragSlider.qml
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ property int value: 50
+ property int maximumValue: 99
+ property alias label: label.text
+ property alias tapEnabled: tap.enabled
+ property alias pressed: tap.pressed
+ signal tapped
+
+ DragHandler {
+ id: dragHandler
+ objectName: root.objectName + " DragHandler"
+ target: knob
+ xAxis.enabled: false
+ yAxis.minimum: slot.y
+ yAxis.maximum: slot.height + slot.y - knob.height
+ }
+
+ Rectangle {
+ id: slot
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: 10
+ anchors.topMargin: 30
+ anchors.bottomMargin: 30
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 10
+ color: "black"
+ radius: width / 2
+ smooth: true
+ }
+
+ Rectangle {
+ id: glow
+ anchors.fill: knob
+ anchors.margins: -5
+ anchors.leftMargin: -2
+ anchors.horizontalCenterOffset: 1
+ radius: 5
+ color: "#4400FFFF"
+ opacity: tap.pressed || tapFlash.running ? 1 : 0
+ FlashAnimation on visible {
+ id: tapFlash
+ }
+ }
+ Rectangle {
+ id: knob
+ objectName: "Slider Knob"
+ width: parent.width - 2
+ height: 20
+ radius: 5
+ color: "darkgray"
+ border.color: "black"
+ property bool programmatic: false
+ property real multiplier: root.maximumValue / (dragHandler.yAxis.maximum - dragHandler.yAxis.minimum)
+ onYChanged: if (!programmatic) root.value = root.maximumValue - (knob.y - dragHandler.yAxis.minimum) * multiplier
+ transformOrigin: Item.Center
+ function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier }
+ TapHandler {
+ id: tap
+ objectName: root.objectName + " TapHandler"
+ gesturePolicy: TapHandler.DragThreshold
+ onTapped: {
+ tapFlash.start()
+ root.tapped
+ }
+ }
+ }
+
+ Text {
+ color: "red"
+ anchors.top: slot.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: root.value
+ }
+
+ Text {
+ id: label
+ font.pointSize: 9
+ color: "red"
+ anchors.bottom: slot.top
+ anchors.bottomMargin: 5
+ anchors.horizontalCenter: parent.horizontalCenter
+ verticalAlignment: Text.AlignBottom
+ }
+
+ Component.onCompleted: {
+ knob.programmatic = true
+ knob.setValue(root.value)
+ knob.programmatic = false
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
new file mode 100644
index 0000000000..b3d621c447
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/KnobDragSlider.qml
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ property int value: 50
+ property int maximumValue: 99
+ property alias label: label.text
+ property alias tapEnabled: tap.enabled
+ property alias pressed: tap.pressed
+ signal tapped
+
+ Rectangle {
+ id: slot
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: 10
+ anchors.topMargin: 30
+ anchors.bottomMargin: 30
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 10
+ color: "black"
+ radius: width / 2
+ smooth: true
+ }
+
+ Rectangle {
+ id: glow
+ anchors.fill: knob
+ anchors.margins: -5
+ anchors.leftMargin: -2
+ anchors.horizontalCenterOffset: 1
+ radius: 5
+ color: "#4400FFFF"
+ opacity: tap.pressed || tapFlash.running ? 1 : 0
+ FlashAnimation on visible {
+ id: tapFlash
+ }
+ }
+ Rectangle {
+ id: knob
+ objectName: "Slider Knob"
+ width: parent.width - 2
+ height: 20
+ radius: 5
+ color: "darkgray"
+ border.color: "black"
+ property bool programmatic: false
+ property real multiplier: root.maximumValue / (dragHandler.yAxis.maximum - dragHandler.yAxis.minimum)
+ onYChanged: if (!programmatic) root.value = root.maximumValue - (knob.y - dragHandler.yAxis.minimum) * multiplier
+ transformOrigin: Item.Center
+ function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier }
+ DragHandler {
+ id: dragHandler
+ objectName: root.objectName + " DragHandler"
+ xAxis.enabled: false
+ yAxis.minimum: slot.y
+ yAxis.maximum: slot.height + slot.y - knob.height
+ }
+ TapHandler {
+ id: tap
+ objectName: root.objectName + " TapHandler"
+ gesturePolicy: TapHandler.DragThreshold
+ onTapped: {
+ tapFlash.start()
+ root.tapped
+ }
+ }
+ }
+
+ Text {
+ color: "red"
+ anchors.top: slot.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: root.value
+ }
+
+ Text {
+ id: label
+ font.pointSize: 9
+ color: "red"
+ anchors.bottom: slot.top
+ anchors.bottomMargin: 5
+ anchors.horizontalCenter: parent.horizontalCenter
+ verticalAlignment: Text.AlignBottom
+ }
+
+ Component.onCompleted: {
+ knob.programmatic = true
+ knob.setValue(root.value)
+ knob.programmatic = false
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
new file mode 100644
index 0000000000..2c9fa30a70
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ property alias label: label.text
+ property alias pressed: tap.pressed
+ property bool checked: false
+ property alias gesturePolicy: tap.gesturePolicy
+ property alias enabled: tap.enabled
+ signal tapped
+
+ width: label.implicitWidth * 1.5; height: label.implicitHeight * 2.0
+ border.color: "#9f9d9a"; border.width: 1; radius: height / 4; antialiasing: true
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: tap.pressed ? "#b8b5b2" : "#efebe7" }
+ GradientStop { position: 1.0; color: "#b8b5b2" }
+ }
+
+ TapHandler {
+ id: tap
+ objectName: label.text
+ longPressThreshold: 100 // CI can be insanely slow, so don't demand a timely release to generate onTapped
+ onTapped: {
+ tapFlash.start()
+ root.tapped()
+ }
+ }
+
+ Text {
+ id: label
+ font.pointSize: 14
+ text: "Button"
+ anchors.centerIn: parent
+ }
+
+ Rectangle {
+ anchors.fill: parent; anchors.margins: -5
+ color: "transparent"; border.color: "#4400FFFF"
+ border.width: 5; radius: root.radius; antialiasing: true
+ opacity: tapFlash.running ? 1 : 0
+ FlashAnimation on visible { id: tapFlash }
+ }
+
+ Rectangle {
+ objectName: "expandingCircle"
+ radius: tap.timeHeld * 100
+ visible: radius > 0 && tap.pressed
+ border.width: 3
+ border.color: "cyan"
+ color: "transparent"
+ width: radius * 2
+ height: radius * 2
+ x: tap.point.scenePressPosition.x - radius
+ y: tap.point.scenePressPosition.y - radius
+ opacity: 0.25
+ Component.onCompleted: {
+ // get on top of all the buttons
+ var par = root.parent;
+ while (par.parent)
+ par = par.parent;
+ parent = par;
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml
new file mode 100644
index 0000000000..fd32baad10
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnFlickable.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Flickable {
+ id: root
+ objectName: "root"
+ width: 800
+ height: 480
+ contentWidth: 1000
+ contentHeight: 600
+
+ Rectangle {
+ anchors.fill: parent
+ color: "transparent"
+ border.color: "black"
+ }
+
+ Rectangle {
+ objectName: "button"
+ anchors.centerIn: parent
+ border.color: "tomato"
+ border.width: 10
+ color: buttonDrag.active ? "goldenrod" : "beige"
+ width: 100
+ height: 100
+ DragHandler {
+ id: buttonDrag
+ objectName: "buttonDrag"
+ }
+ }
+
+ DragHandler {
+ id: contentItemDrag
+ objectName: "contentItemDrag"
+ }
+ Text {
+ x: 100; y: 100
+ text: "dragging contentItem"
+ visible: contentItemDrag.active
+ }
+
+ Component.onCompleted: contentItem.objectName = "Flickable's contentItem"
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
new file mode 100644
index 0000000000..bb39c2267c
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+ListView {
+ id: root
+ objectName: "root"
+ property Item buttonUnderTest: null
+ property Item delegateUnderTest: null
+ width: 800
+ height: 480
+ model: 10
+ spacing: 2
+
+ delegate: Rectangle {
+ objectName: "itemview delegate"
+ color: delegateDrag.active ? "wheat" : "beige"
+ border.color: "black"
+ width: parent.width; height: 140
+ Rectangle {
+ objectName: "button"
+ x: 350; y: 20
+ border.color: "tomato"
+ border.width: 10
+ color: buttonDrag.active ? "goldenrod" : "beige"
+ width: 100
+ height: 100
+ DragHandler {
+ id: buttonDrag
+ objectName: "buttonDrag"
+ }
+ Component.onCompleted: if (!root.buttonUnderTest) {
+ root.buttonUnderTest = this
+ root.delegateUnderTest = parent
+ }
+ }
+ DragHandler {
+ id: delegateDrag
+ objectName: "delegateDrag"
+ }
+ }
+
+ DragHandler {
+ objectName: "contentItemDrag"
+ }
+
+ Component.onCompleted: contentItem.objectName = "ListView's contentItem"
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml
new file mode 100644
index 0000000000..43cc44f62e
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+TableView {
+ id: root
+ objectName: "root"
+ property Item buttonUnderTest: null
+ property Item delegateUnderTest: null
+ width: 800
+ height: 480
+ columnSpacing: 2
+ rowSpacing: 2
+ // TODO use TableModel when it's ready, to test with multiple columns
+ model: 10
+
+ delegate: Rectangle {
+ id: tableDelegate
+ objectName: "itemview delegate"
+ color: delegateDrag.active ? "wheat" : "beige"
+ implicitWidth: 200
+ implicitHeight: 140
+
+ Rectangle {
+ objectName: "button"
+ x: 50; y: 20
+ border.color: "tomato"
+ border.width: 10
+ color: buttonDrag.active ? "goldenrod" : "beige"
+ width: 100
+ height: 100
+ DragHandler {
+ id: buttonDrag
+ objectName: "buttonDrag"
+ }
+ Component.onCompleted: if (!root.buttonUnderTest) {
+ root.buttonUnderTest = this
+ root.delegateUnderTest = parent
+ }
+ }
+
+ DragHandler {
+ id: delegateDrag
+ objectName: "delegateDrag"
+ }
+ }
+
+ DragHandler {
+ objectName: "contentItemDrag"
+ }
+
+ Component.onCompleted: contentItem.objectName = "TableView's contentItem"
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
new file mode 100644
index 0000000000..5693a6acd2
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ width: 800
+ height: 480
+ objectName: "root"
+ color: "#222222"
+
+ Flickable {
+ anchors.fill: parent
+ anchors.margins: 10
+ anchors.topMargin: 40
+ contentHeight: 600
+ contentWidth: 1000
+// pressDelay: TODO
+
+ Row {
+ spacing: 6
+ KnobDragSlider {
+ label: "Slider with\nDH on knob"
+ objectName: "knobSlider"
+ value: 49; width: 120; height: 400
+ }
+ GrooveDragSlider {
+ label: "Slider with\nDH on root"
+ objectName: "grooveSlider"
+ value: 49; width: 120; height: 400
+ }
+ Column {
+ spacing: 6
+ TapHandlerButton {
+ objectName: "DragThreshold"
+ label: "DragThreshold"
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ TapHandlerButton {
+ objectName: "WithinBounds"
+ label: "WithinBounds"
+ gesturePolicy: TapHandler.WithinBounds
+ }
+ TapHandlerButton {
+ objectName: "ReleaseWithinBounds"
+ label: "ReleaseWithinBounds"
+ gesturePolicy: TapHandler.ReleaseWithinBounds // the default
+ }
+ }
+ Column {
+ spacing: 6
+ Rectangle {
+ width: 50
+ height: 50
+ color: "aqua"
+ border.color: drag1.active ? "darkgreen" : "transparent"
+ border.width: 3
+ objectName: "drag"
+ DragHandler {
+ id: drag1
+ objectName: "drag1"
+ }
+ Text {
+ anchors.centerIn: parent
+ enabled: false
+ text: "drag"
+ }
+ }
+ Rectangle {
+ width: 50
+ height: 50
+ color: "aqua"
+ objectName: "tap"
+ border.color: tap1.isPressed ? "red" : "transparent"
+ border.width: 3
+ TapHandler {
+ id: tap1
+ objectName: "tap1"
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ Text {
+ anchors.centerIn: parent
+ enabled: false
+ text: "tap"
+ }
+ }
+ Rectangle {
+ width: 50
+ height: 50
+ color: "aqua"
+ border.color: tap2.isPressed ? "red" : drag2.active ? "darkgreen" : "transparent"
+ border.width: 3
+ objectName: "dragAndTap"
+ DragHandler {
+ id: drag2
+ objectName: "drag2"
+ }
+ TapHandler {
+ id: tap2
+ objectName: "tap2"
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ Text {
+ anchors.centerIn: parent
+ enabled: false
+ text: "drag\nand\ntap"
+ }
+ }
+ Rectangle {
+ width: 50
+ height: 50
+ color: "aqua"
+ border.color: tap3.isPressed ? "red" : drag3.active ? "darkgreen" : "transparent"
+ border.width: 3
+ objectName: "tapAndDrag"
+ TapHandler {
+ id: tap3
+ objectName: "tap3"
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ DragHandler {
+ id: drag3
+ objectName: "drag3"
+ }
+ Text {
+ anchors.centerIn: parent
+ enabled: false
+ text: "tap\nand\ndrag"
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml
new file mode 100644
index 0000000000..a71db0b4c2
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnFlickable.qml
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Flickable {
+ id: root
+ objectName: "root"
+ width: 800
+ height: 480
+ contentWidth: 1000
+ contentHeight: 600
+
+ Rectangle {
+ objectName: "button"
+ anchors.centerIn: parent
+ border.color: "tomato"
+ border.width: 10
+ color: innerTap.pressed ? "wheat" : "transparent"
+ width: 100
+ height: 100
+ TapHandler {
+ id: innerTap
+ objectName: "buttonTap"
+ }
+ }
+
+ TapHandler {
+ objectName: "contentItemTap"
+ }
+ Component.onCompleted: contentItem.objectName = "Flickable's contentItem"
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml
new file mode 100644
index 0000000000..ef27955043
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+ListView {
+ id: root
+ objectName: "root"
+ property Item buttonUnderTest: null
+ property Item delegateUnderTest: null
+ width: 800
+ height: 480
+ model: 10
+ spacing: 2
+
+ delegate: Rectangle {
+ objectName: "itemview delegate"
+ color: delegateTap.pressed ? "wheat" : "beige"
+ width: parent.width; height: 140
+ Rectangle {
+ objectName: "button"
+ anchors.centerIn: parent
+ border.color: "tomato"
+ border.width: 10
+ color: innerTap.pressed ? "goldenrod" : "beige"
+ width: 100
+ height: 100
+ TapHandler {
+ id: innerTap
+ objectName: "buttonTap"
+ }
+ Component.onCompleted: if (!root.buttonUnderTest) {
+ root.buttonUnderTest = this
+ root.delegateUnderTest = parent
+ }
+ }
+ TapHandler {
+ id: delegateTap
+ objectName: "delegateTap"
+ }
+ }
+
+ TapHandler {
+ objectName: "contentItemTap"
+ }
+
+ Component.onCompleted: contentItem.objectName = "ListView's contentItem"
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml
new file mode 100644
index 0000000000..6bf1054d7a
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+TableView {
+ id: root
+ objectName: "root"
+ property Item buttonUnderTest: null
+ property Item delegateUnderTest: null
+ width: 800
+ height: 480
+ columnSpacing: 2
+ rowSpacing: 2
+ // TODO use TableModel when it's ready, to test with multiple columns
+ model: 10
+
+ delegate: Rectangle {
+ id: tableDelegate
+ objectName: "itemview delegate"
+ color: delegateTap.pressed ? "wheat" : "beige"
+ implicitWidth: 200
+ implicitHeight: 140
+
+ Rectangle {
+ objectName: "button"
+ anchors.centerIn: parent
+ border.color: "tomato"
+ border.width: 10
+ color: innerTap.pressed ? "goldenrod" : "beige"
+ width: 100
+ height: 100
+ TapHandler {
+ id: innerTap
+ objectName: "buttonTap"
+ }
+ Component.onCompleted: if (!root.buttonUnderTest) {
+ root.buttonUnderTest = this
+ root.delegateUnderTest = parent
+ }
+ }
+
+ TapHandler {
+ id: delegateTap
+ objectName: "delegateTap"
+ }
+ }
+
+ TapHandler {
+ objectName: "contentItemTap"
+ }
+
+ Component.onCompleted: contentItem.objectName = "TableView's contentItem"
+}
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/flickableinterop.pro b/tests/auto/quick/pointerhandlers/flickableinterop/flickableinterop.pro
new file mode 100644
index 0000000000..9075044bd3
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/flickableinterop.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+
+TARGET = tst_flickableinterop
+QT += core-private gui-private qml-private quick-private testlib
+
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_flickableinterop.cpp
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/flickableWithHandlers.qml data/Slider.qml
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
new file mode 100644
index 0000000000..f4ed051e1f
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
@@ -0,0 +1,799 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtGui/qstylehints.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickflickable_p.h>
+#include <QtQuick/private/qquickitemview_p.h>
+#include <QtQuick/private/qquickpointerhandler_p.h>
+#include <QtQuick/private/qquickdraghandler_p.h>
+#include <QtQuick/private/qquicktaphandler_p.h>
+#include <QtQuick/private/qquicktableview_p.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <private/qquickwindow_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlproperty.h>
+
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+class tst_FlickableInterop : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_FlickableInterop()
+ :touchDevice(QTest::createTouchDevice())
+ {}
+
+private slots:
+ void touchTapButton_data();
+ void touchTapButton();
+ void touchDragFlickableBehindButton_data();
+ void touchDragFlickableBehindButton();
+ void mouseClickButton_data();
+ void mouseClickButton();
+ void mouseDragFlickableBehindButton_data();
+ void mouseDragFlickableBehindButton();
+ void touchDragSlider();
+ void touchDragFlickableBehindSlider();
+ void mouseDragSlider_data();
+ void mouseDragSlider();
+ void mouseDragFlickableBehindSlider();
+ void touchDragFlickableBehindItemWithHandlers_data();
+ void touchDragFlickableBehindItemWithHandlers();
+ void mouseDragFlickableBehindItemWithHandlers_data();
+ void mouseDragFlickableBehindItemWithHandlers();
+ void touchDragSliderAndFlickable();
+ void touchAndDragHandlerOnFlickable_data();
+ void touchAndDragHandlerOnFlickable();
+
+private:
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+ QTouchDevice *touchDevice;
+};
+
+void tst_FlickableInterop::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+{
+ window.reset(new QQuickView);
+ window->setSource(testFileUrl(fileName));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+}
+
+void tst_FlickableInterop::touchTapButton_data()
+{
+ QTest::addColumn<QString>("buttonName");
+ QTest::newRow("DragThreshold") << QStringLiteral("DragThreshold");
+ QTest::newRow("WithinBounds") << QStringLiteral("WithinBounds");
+ QTest::newRow("ReleaseWithinBounds") << QStringLiteral("ReleaseWithinBounds");
+}
+
+void tst_FlickableInterop::touchTapButton()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QFETCH(QString, buttonName);
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>(buttonName);
+ QVERIFY(button);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+
+ // Button changes pressed state and emits tapped on release
+ QPoint p1 = button->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 1);
+
+ // We can drag <= dragThreshold and the button still acts normal, Flickable doesn't grab
+ p1 = button->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(button->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 2);
+}
+
+void tst_FlickableInterop::touchDragFlickableBehindButton_data()
+{
+ QTest::addColumn<QString>("buttonName");
+ QTest::newRow("DragThreshold") << QStringLiteral("DragThreshold");
+ QTest::newRow("WithinBounds") << QStringLiteral("WithinBounds");
+ QTest::newRow("ReleaseWithinBounds") << QStringLiteral("ReleaseWithinBounds");
+}
+
+void tst_FlickableInterop::touchDragFlickableBehindButton()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QFETCH(QString, buttonName);
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>(buttonName);
+ QVERIFY(button);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+
+ tappedSpy.clear();
+ QPoint p1 = button->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(button->property("pressed").toBool());
+ int i = 0;
+ // Start dragging; eventually when the touchpoint goes beyond dragThreshold,
+ // Button is no longer pressed because Flickable steals the grab
+ for (; i < 100 && !flickable->isMoving(); ++i) {
+ p1 += QPoint(1, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ }
+ qCDebug(lcPointerTests) << "flickable started moving after" << i << "moves, when we got to" << p1;
+ QVERIFY(flickable->isMoving());
+ QCOMPARE(i, 2);
+ QVERIFY(!button->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 0);
+}
+
+void tst_FlickableInterop::mouseClickButton_data()
+{
+ QTest::addColumn<QString>("buttonName");
+ QTest::newRow("DragThreshold") << QStringLiteral("DragThreshold");
+ QTest::newRow("WithinBounds") << QStringLiteral("WithinBounds");
+ QTest::newRow("ReleaseWithinBounds") << QStringLiteral("ReleaseWithinBounds");
+}
+
+void tst_FlickableInterop::mouseClickButton()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QFETCH(QString, buttonName);
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>(buttonName);
+ QVERIFY(button);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+
+ // Button changes pressed state and emits tapped on release
+ QPoint p1 = button->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 1);
+
+ // We can drag <= dragThreshold and the button still acts normal, Flickable doesn't grab
+ p1 = button->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1, qApp->styleHints()->mouseDoubleClickInterval() + 10);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ QVERIFY(button->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 2);
+}
+
+void tst_FlickableInterop::mouseDragFlickableBehindButton_data()
+{
+ QTest::addColumn<QString>("buttonName");
+ QTest::newRow("DragThreshold") << QStringLiteral("DragThreshold");
+ QTest::newRow("WithinBounds") << QStringLiteral("WithinBounds");
+ QTest::newRow("ReleaseWithinBounds") << QStringLiteral("ReleaseWithinBounds");
+}
+
+void tst_FlickableInterop::mouseDragFlickableBehindButton()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QFETCH(QString, buttonName);
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>(buttonName);
+ QVERIFY(button);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+
+ // Button is no longer pressed if touchpoint goes beyond dragThreshold,
+ // because Flickable steals the grab
+ tappedSpy.clear();
+ QPoint p1 = button->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QVERIFY(button->property("pressed").toBool());
+ int i = 0;
+ for (; i < 100 && !flickable->isMoving(); ++i) {
+ p1 += QPoint(1, 0);
+ QTest::mouseMove(window, p1);
+ }
+ qCDebug(lcPointerTests) << "flickable started moving after" << i << "moves, when we got to" << p1;
+ QVERIFY(flickable->isMoving());
+ QCOMPARE(i, 2);
+ QVERIFY(!button->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 0);
+}
+
+void tst_FlickableInterop::touchDragSlider()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider");
+ QVERIFY(slider);
+ QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
+ QVERIFY(drag);
+ QQuickItem *knob = slider->findChild<QQuickItem*>("Slider Knob");
+ QVERIFY(knob);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
+ QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
+
+ // Drag the slider in the allowed (vertical) direction
+ tappedSpy.clear();
+ QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint() - QPoint(0, 8);
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(slider->property("pressed").toBool());
+ p1 += QPoint(0, dragThreshold);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(slider->property("pressed").toBool());
+ QCOMPARE(slider->property("value").toInt(), 49);
+ p1 += QPoint(0, 1);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(0, 10);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(slider->property("value").toInt() < 49);
+ QVERIFY(!flickable->isMoving());
+ QVERIFY(!slider->property("pressed").toBool());
+
+ // Now that the DragHandler is active, the Flickable will not steal the grab
+ // even if we move a large distance horizontally
+ p1 += QPoint(dragThreshold * 2, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!flickable->isMoving());
+
+ // Release, and do not expect the tapped signal
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(translationChangedSpy.count(), 1);
+}
+
+void tst_FlickableInterop::mouseDragSlider_data()
+{
+ QTest::addColumn<QString>("nameOfSliderToDrag");
+ QTest::addColumn<QPoint>("pressPositionRelativeToKnob");
+ QTest::addColumn<QPoint>("dragDirection"); // a unit vector
+ QTest::addColumn<bool>("expectedTapHandlerPressed");
+ QTest::addColumn<bool>("expectedDragHandlerActive");
+ QTest::addColumn<bool>("expectedFlickableMoving");
+
+ QTest::newRow("drag down on knob of knobSlider") << "knobSlider" << QPoint(0, -8) << QPoint(0, 1) << true << true << false;
+ QTest::newRow("drag sideways on knob of knobSlider") << "knobSlider" << QPoint(0, 0) << QPoint(1, 0) << true << false << true;
+ QTest::newRow("drag down on groove of knobSlider") << "knobSlider" << QPoint(0, 20) << QPoint(0, 1) << false << false << true;
+ QTest::newRow("drag sideways on groove of knobSlider") << "knobSlider" << QPoint(0, 20) << QPoint(1, 0) << false << false << true;
+
+ QTest::newRow("drag down on knob of grooveSlider") << "grooveSlider" << QPoint(0, -8) << QPoint(0, 1) << true << true << false;
+ QTest::newRow("drag sideways on knob of grooveSlider") << "grooveSlider" << QPoint(0, 0) << QPoint(1, 0) << true << false << true;
+ QTest::newRow("drag down on groove of grooveSlider") << "grooveSlider" << QPoint(0, 20) << QPoint(0, 1) << false << true << false;
+ QTest::newRow("drag sideways on groove of grooveSlider") << "grooveSlider" << QPoint(0, 20) << QPoint(1, 0) << false << false << true;
+}
+
+void tst_FlickableInterop::mouseDragSlider()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QFETCH(QString, nameOfSliderToDrag);
+ QFETCH(QPoint, pressPositionRelativeToKnob);
+ QFETCH(QPoint, dragDirection); // a unit vector
+ QFETCH(bool, expectedTapHandlerPressed);
+ QFETCH(bool, expectedDragHandlerActive);
+ QFETCH(bool, expectedFlickableMoving);
+
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>(nameOfSliderToDrag);
+ QVERIFY(slider);
+ QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
+ QVERIFY(drag);
+ QQuickItem *knob = slider->findChild<QQuickItem*>("Slider Knob");
+ QVERIFY(knob);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
+ QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
+
+ // Drag the slider
+ tappedSpy.clear();
+ QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint() + pressPositionRelativeToKnob;
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(slider->property("pressed").toBool(), expectedTapHandlerPressed);
+ p1 += QPoint(dragThreshold * dragDirection.x(), dragThreshold * dragDirection.y());
+ QTest::mouseMove(window, p1);
+ QCOMPARE(drag->active(), false);
+ QCOMPARE(slider->property("pressed").toBool(), expectedTapHandlerPressed);
+ QCOMPARE(slider->property("value").toInt(), 49);
+ p1 += dragDirection; // one more pixel
+ QTest::mouseMove(window, p1);
+ // After moving by the drag threshold, the point should still be inside the knob.
+ // However, QQuickTapHandler::wantsEventPoint() returns false because the drag threshold is exceeded.
+ // Therefore QQuickTapHandler::setPressed(false, true, point) is called: the active state is canceled.
+ QCOMPARE(slider->property("pressed").toBool(), false);
+ QCOMPARE(drag->active(), expectedDragHandlerActive);
+ // drag farther, to make sure the knob gets adjusted significantly
+ p1 += QPoint(10 * dragDirection.x(), 10 * dragDirection.y());
+ QTest::mouseMove(window, p1);
+ if (expectedDragHandlerActive && dragDirection.y() > 0)
+ QVERIFY(slider->property("value").toInt() < 49);
+ // by now, Flickable will have stolen the grab, if it decided that it wanted to during filtering of the last event
+ QCOMPARE(flickable->isMoving(), expectedFlickableMoving);
+ QCOMPARE(slider->property("pressed").toBool(), false);
+
+ // If the DragHandler is active, the Flickable will not steal the grab
+ // even if we move a large distance horizontally
+ if (expectedDragHandlerActive) {
+ p1 += QPoint(dragThreshold * 2, 0);
+ QTest::mouseMove(window, p1);
+ QCOMPARE(flickable->isMoving(), false);
+ }
+
+ // Release, and do not expect the tapped signal
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(translationChangedSpy.count(), expectedDragHandlerActive ? 1 : 0);
+}
+
+void tst_FlickableInterop::touchDragFlickableBehindSlider()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider");
+ QVERIFY(slider);
+ QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
+ QVERIFY(drag);
+ QQuickItem *knob = slider->findChild<QQuickItem*>("Slider Knob");
+ QVERIFY(knob);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
+ QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
+
+ // Button is no longer pressed if touchpoint goes beyond dragThreshold,
+ // because Flickable steals the grab
+ tappedSpy.clear();
+ QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(slider->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(slider->property("pressed").toBool());
+ int i = 0;
+ for (; i < 100 && !flickable->isMoving(); ++i) {
+ p1 += QPoint(1, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ }
+ qCDebug(lcPointerTests) << "flickable started moving after" << i << "moves, when we got to" << p1;
+ QVERIFY(flickable->isMoving());
+ QCOMPARE(i, 2);
+ QVERIFY(!slider->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!slider->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(translationChangedSpy.count(), 0);
+}
+
+void tst_FlickableInterop::mouseDragFlickableBehindSlider()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider");
+ QVERIFY(slider);
+ QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
+ QVERIFY(drag);
+ QQuickItem *knob = slider->findChild<QQuickItem*>("Slider Knob");
+ QVERIFY(knob);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped()));
+ QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged()));
+
+ // Button is no longer pressed if touchpoint goes beyond dragThreshold,
+ // because Flickable steals the grab
+ tappedSpy.clear();
+ QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(slider->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(slider->property("pressed").toBool());
+ int i = 0;
+ for (; i < 100 && !flickable->isMoving(); ++i) {
+ p1 += QPoint(1, 0);
+ QTest::mouseMove(window, p1);
+ }
+ qCDebug(lcPointerTests) << "flickable started moving after" << i << "moves, when we got to" << p1;
+ QVERIFY(flickable->isMoving());
+ QCOMPARE(i, 2);
+ QVERIFY(!slider->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(translationChangedSpy.count(), 0);
+}
+
+void tst_FlickableInterop::touchDragFlickableBehindItemWithHandlers_data()
+{
+ QTest::addColumn<QByteArray>("nameOfRectangleToDrag");
+ QTest::addColumn<bool>("expectedFlickableMoving");
+ QTest::newRow("drag") << QByteArray("drag") << false;
+ QTest::newRow("tap") << QByteArray("tap") << true;
+ QTest::newRow("dragAndTap") << QByteArray("dragAndTap") << false;
+ QTest::newRow("tapAndDrag") << QByteArray("tapAndDrag") << false;
+}
+
+void tst_FlickableInterop::touchDragFlickableBehindItemWithHandlers()
+{
+ QFETCH(bool, expectedFlickableMoving);
+ QFETCH(QByteArray, nameOfRectangleToDrag);
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>(nameOfRectangleToDrag);
+ QVERIFY(rect);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QPoint p1 = rect->mapToScene(rect->clipRect().center()).toPoint();
+ QPoint originP1 = p1;
+
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ for (int i = 0; i < dragThreshold * 3; ++i) {
+ p1 = originP1;
+ p1.rx() += i;
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(flickable->isMoving(), expectedFlickableMoving);
+ if (!expectedFlickableMoving) {
+ QVERIFY(rect->mapToScene(rect->clipRect().center()).toPoint().x() > originP1.x());
+ }
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+}
+
+void tst_FlickableInterop::mouseDragFlickableBehindItemWithHandlers_data()
+{
+ touchDragFlickableBehindItemWithHandlers_data();
+}
+
+void tst_FlickableInterop::mouseDragFlickableBehindItemWithHandlers()
+{
+ QFETCH(bool, expectedFlickableMoving);
+ QFETCH(QByteArray, nameOfRectangleToDrag);
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>(nameOfRectangleToDrag);
+ QVERIFY(rect);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QPoint p1 = rect->mapToScene(rect->clipRect().center()).toPoint();
+ QPoint originP1 = p1;
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ for (int i = 0; i < 3; ++i) {
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(flickable->isMoving(), expectedFlickableMoving);
+ if (!expectedFlickableMoving) {
+ QCOMPARE(originP1 + QPoint(3*dragThreshold, 0), p1);
+ }
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ // wait until flickable stops
+ QTRY_COMPARE(flickable->isMoving(), false);
+
+ // After the mouse button has been released, move the mouse and ensure that nothing is moving
+ // because of that (this tests if all grabs are released when the mouse button is released).
+ p1 = rect->mapToScene(rect->clipRect().center()).toPoint();
+ originP1 = p1;
+ for (int i = 0; i < 3; ++i) {
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(flickable->isMoving(), false);
+ QCOMPARE(originP1, rect->mapToScene(rect->clipRect().center()).toPoint());
+}
+
+void tst_FlickableInterop::touchDragSliderAndFlickable()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("knobSlider");
+ QVERIFY(slider);
+ QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
+ QVERIFY(drag);
+ QQuickItem *knob = slider->findChild<QQuickItem*>("Slider Knob");
+ QVERIFY(knob);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
+
+ // The knob is initially centered over the slider's "groove"
+ qreal initialXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).x() - slider->mapToScene
+ (slider->clipRect().center()).x());
+ QVERIFY(initialXOffset <= 1);
+
+ // Drag the slider in the allowed (vertical) direction with one finger
+ QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint();
+ touchSeq.press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(0, dragThreshold);
+ touchSeq.move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(0, dragThreshold);
+ touchSeq.move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(0, dragThreshold);
+ touchSeq.move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(slider->property("value").toInt() < 49);
+ QVERIFY(!flickable->isMoving());
+
+ // Drag the Flickable with a second finger
+ QPoint p2(300,300);
+ touchSeq.stationary(1).press(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ for (int i = 0; i < 4; ++i) {
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ touchSeq.move(1, p1, window).stationary(2).commit();
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ touchSeq.stationary(1).move(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ qCDebug(lcPointerTests) << "step" << i << ": fingers @" << p1 << p2 << "is Flickable moving yet?" << flickable->isMoving();
+ }
+ QVERIFY(flickable->isMoving());
+ qreal knobSliderXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).toPoint().x() -
+ slider->mapToScene(slider->clipRect().center()).toPoint().x()) - initialXOffset;
+ if (knobSliderXOffset > 1)
+ qCDebug(lcPointerTests) << "knob has slipped out of groove by" << knobSliderXOffset << "pixels";
+ // See if the knob is still centered over the slider's "groove"
+ QVERIFY(qAbs(knobSliderXOffset) <= 1);
+
+ // Release
+ touchSeq.release(1, p1, window).release(2, p2, window).commit();
+}
+
+void tst_FlickableInterop::touchAndDragHandlerOnFlickable_data()
+{
+ QTest::addColumn<QByteArray>("qmlFile");
+ QTest::addColumn<bool>("pressDelay");
+ QTest::addColumn<bool>("targetNull");
+ QTest::newRow("tapOnFlickable") << QByteArray("tapOnFlickable.qml") << false << false;
+ QTest::newRow("tapOnList") << QByteArray("tapOnList.qml") << false << false;
+ QTest::newRow("tapOnTable") << QByteArray("tapOnTable.qml") << false << false;
+ QTest::newRow("dragOnFlickable") << QByteArray("dragOnFlickable.qml") << false << false;
+ QTest::newRow("dragOnList") << QByteArray("dragOnList.qml") << false << false;
+ QTest::newRow("dragOnTable") << QByteArray("dragOnTable.qml") << false << false;
+ QTest::newRow("tapDelayOnFlickable") << QByteArray("tapOnFlickable.qml") << true << false;
+ QTest::newRow("tapDelayOnList") << QByteArray("tapOnList.qml") << true << false;
+ QTest::newRow("tapDelayOnTable") << QByteArray("tapOnTable.qml") << true << false;
+ QTest::newRow("dragDelayOnFlickable") << QByteArray("dragOnFlickable.qml") << true << false;
+ QTest::newRow("dragDelayOnList") << QByteArray("dragOnList.qml") << true << false;
+ QTest::newRow("dragDelayOnTable") << QByteArray("dragOnTable.qml") << true << false;
+ QTest::newRow("tapOnFlickableWithNullTargets") << QByteArray("tapOnFlickable.qml") << false << true;
+ QTest::newRow("tapOnListWithNullTargets") << QByteArray("tapOnList.qml") << false << true;
+ QTest::newRow("tapOnTableWithNullTargets") << QByteArray("tapOnTable.qml") << false << true;
+ QTest::newRow("dragOnFlickableWithNullTargets") << QByteArray("dragOnFlickable.qml") << false << true;
+ QTest::newRow("dragOnListWithNullTargets") << QByteArray("dragOnList.qml") << false << true;
+ QTest::newRow("dragOnTableWithNullTargets") << QByteArray("dragOnTable.qml") << false << true;
+ QTest::newRow("tapDelayOnFlickableWithNullTargets") << QByteArray("tapOnFlickable.qml") << true << true;
+ QTest::newRow("tapDelayOnListWithNullTargets") << QByteArray("tapOnList.qml") << true << true;
+ QTest::newRow("tapDelayOnTableWithNullTargets") << QByteArray("tapOnTable.qml") << true << true;
+ QTest::newRow("dragDelayOnFlickableWithNullTargets") << QByteArray("dragOnFlickable.qml") << true << true;
+ QTest::newRow("dragDelayOnListWithNullTargets") << QByteArray("dragOnList.qml") << true << true;
+ QTest::newRow("dragDelayOnTableWithNullTargets") << QByteArray("dragOnTable.qml") << true << true;
+}
+
+void tst_FlickableInterop::touchAndDragHandlerOnFlickable()
+{
+ QFETCH(QByteArray, qmlFile);
+ QFETCH(bool, pressDelay);
+ QFETCH(bool, targetNull);
+
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, qmlFile.constData());
+ QQuickView * window = windowPtr.data();
+ QQuickFlickable *flickable = qmlobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(flickable);
+ flickable->setPressDelay(pressDelay ? 5000 : 0);
+ QQuickItem *delegate = nullptr;
+ if (QQuickItemView *itemView = qmlobject_cast<QQuickItemView *>(flickable))
+ delegate = itemView->currentItem();
+ if (!delegate)
+ delegate = flickable->property("delegateUnderTest").value<QQuickItem*>();
+ QQuickItem *button = delegate ? delegate->findChild<QQuickItem*>("button")
+ : flickable->findChild<QQuickItem*>("button");
+ if (!button)
+ button = flickable->property("buttonUnderTest").value<QQuickItem*>();
+ QVERIFY(button);
+ QQuickPointerHandler *buttonHandler = button->findChild<QQuickPointerHandler*>();
+ QVERIFY(buttonHandler);
+ QQuickTapHandler *buttonTapHandler = qmlobject_cast<QQuickTapHandler *>(buttonHandler);
+ QQuickDragHandler *buttonDragHandler = qmlobject_cast<QQuickDragHandler *>(buttonHandler);
+ QQuickPointerHandler *delegateHandler = delegate ? delegate->findChild<QQuickPointerHandler*>() : nullptr;
+ QQuickPointerHandler *contentItemHandler = flickable->findChild<QQuickPointerHandler*>();
+ QVERIFY(contentItemHandler);
+ // a handler declared directly in a Flickable (or item view) must actually be a child of the contentItem,
+ // just as Items declared inside are (QTBUG-71918 and QTBUG-73035)
+ QCOMPARE(contentItemHandler->parentItem(), flickable->contentItem());
+ if (targetNull) {
+ buttonHandler->setTarget(nullptr);
+ if (delegateHandler)
+ delegateHandler->setTarget(nullptr);
+ contentItemHandler->setTarget(nullptr);
+ }
+
+ // Drag one finger on the Flickable and make sure it flicks
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
+ QPoint p1(780, 460);
+ touchSeq.press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ for (int i = 0; i < 4; ++i) {
+ p1 -= QPoint(dragThreshold, dragThreshold);
+ touchSeq.move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ }
+ if (!(buttonDragHandler && !pressDelay))
+ QTRY_VERIFY(flickable->contentY() >= dragThreshold);
+ if (buttonTapHandler)
+ QCOMPARE(buttonTapHandler->isPressed(), false);
+ touchSeq.release(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+
+ // Drag one finger on the delegate and make sure Flickable flicks
+ if (delegate) {
+ flickable->setContentY(0);
+ QTRY_COMPARE(flickable->isMoving(), false);
+ QVERIFY(delegateHandler);
+ QQuickTapHandler *delegateTapHandler = qmlobject_cast<QQuickTapHandler *>(delegateHandler);
+ p1 = button->mapToScene(button->clipRect().bottomRight()).toPoint() + QPoint(10, 0);
+ touchSeq.press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ if (delegateTapHandler && !pressDelay)
+ QCOMPARE(delegateTapHandler->isPressed(), true);
+ for (int i = 0; i < 4; ++i) {
+ p1 -= QPoint(dragThreshold, dragThreshold);
+ touchSeq.move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ if (i > 1)
+ QTRY_VERIFY(delegateHandler->active() || flickable->isMoving());
+ }
+ if (!(buttonDragHandler && !pressDelay))
+ QVERIFY(flickable->contentY() > 0);
+ if (delegateTapHandler)
+ QCOMPARE(delegateTapHandler->isPressed(), false);
+ touchSeq.release(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ }
+
+ // Drag one finger on the button and make sure Flickable flicks
+ flickable->setContentY(0);
+ QTRY_COMPARE(flickable->isMoving(), false);
+ p1 = button->mapToScene(button->clipRect().center()).toPoint();
+ touchSeq.press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ if (buttonTapHandler && !pressDelay)
+ QTRY_COMPARE(buttonTapHandler->isPressed(), true);
+ for (int i = 0; i < 4; ++i) {
+ p1 -= QPoint(dragThreshold, dragThreshold);
+ touchSeq.move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ }
+ if (!(buttonDragHandler && !pressDelay))
+ QVERIFY(flickable->contentY() > 0);
+ if (buttonTapHandler)
+ QCOMPARE(buttonTapHandler->isPressed(), false);
+ touchSeq.release(1, p1, window).commit();
+}
+
+QTEST_MAIN(tst_FlickableInterop)
+
+#include "tst_flickableinterop.moc"
+
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
new file mode 100644
index 0000000000..f1591a412e
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ width: 1024; height: 600
+ color: "beige"
+ objectName: "beige root"
+
+ Rectangle {
+ id: container
+ objectName: "container rect"
+ width: 600
+ height: 500
+ color: "black"
+ border.color: pinch3.active ? "red" : "black"
+ border.width: 3
+ antialiasing: true
+
+ MultiPointTouchArea {
+ id: mpta
+ anchors.fill: parent
+ //onGestureStarted: gesture.grab() // in case this is embedded in something that might steal
+ touchPoints: [
+ TouchPoint { property color color: "red" },
+ TouchPoint { property color color: "orange" },
+ TouchPoint { property color color: "lightsteelblue" },
+ TouchPoint { property color color: "green" }
+ ] }
+
+ Repeater {
+ model: 4
+
+ Item {
+ id: crosshairs
+ property TouchPoint touchPoint
+ x: touchPoint.x - width / 2
+ y: touchPoint.y - height / 2
+ width: 300; height: 300
+ visible: touchPoint.pressed
+ rotation: touchPoint.rotation
+
+ Rectangle {
+ color: touchPoint.color
+ anchors.centerIn: parent
+ width: 2; height: parent.height
+ antialiasing: true
+ }
+ Rectangle {
+ color: touchPoint.color
+ anchors.centerIn: parent
+ width: parent.width; height: 2
+ antialiasing: true
+ }
+ Component.onCompleted: touchPoint = mpta.touchPoints[index]
+ }
+ }
+
+ Item {
+ objectName: "pinch and drag"
+ anchors.fill: parent
+ // In order for PinchHandler to get a chance to take a passive grab, it has to get the touchpoints first.
+ // In order to get the touchpoints first, it has to be on top of the Z order: i.e. come last in paintOrderChildItems().
+ // This is the opposite situation as with filtersChildMouseEvents: e.g. PinchArea would have wanted to be the parent,
+ // if it even knew that trick (which it doesn't).
+ DragHandler {
+ id: dragHandler
+ objectName: "DragHandler"
+ target: container
+ grabPermissions: PointerHandler.CanTakeOverFromItems
+ }
+ PinchHandler {
+ id: pinch3
+ objectName: "3-finger pinch"
+ target: container
+ minimumPointCount: 3
+ minimumScale: 0.1
+ maximumScale: 10
+ grabPermissions: PointerHandler.CanTakeOverFromItems
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml
new file mode 100644
index 0000000000..1bd20c6bcb
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/unloadHandlerOnPress.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ width: 640
+ height: 480
+
+ Loader {
+ id: loader
+
+ width: 480
+ height: 480
+
+ sourceComponent: Rectangle {
+ id: item2
+ anchors.fill: parent
+ color: "blue"
+
+ DragHandler{}
+ }
+ }
+
+ Rectangle {
+ color: "yellow"
+ width: 180
+ height: 180
+
+ MultiPointTouchArea {
+ anchors.fill: parent
+ touchPoints: [
+ TouchPoint { onPressedChanged: loader.sourceComponent = undefined }
+ ]
+ }
+ }
+}
+
+
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/multipointtoucharea_interop.pro b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/multipointtoucharea_interop.pro
new file mode 100644
index 0000000000..10d0ff8018
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/multipointtoucharea_interop.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+
+TARGET = tst_multipointtoucharea_interop
+QT += core-private gui-private qml-private quick-private testlib
+
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_multipointtoucharea_interop.cpp
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/pinchDragMPTA.qml
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
new file mode 100644
index 0000000000..bf582b820b
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlproperty.h>
+#include <QtQuick/private/qquickdraghandler_p.h>
+#include <QtQuick/private/qquickmultipointtoucharea_p.h>
+#include <QtQuick/private/qquickpinchhandler_p.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
+
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+class tst_MptaInterop : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_MptaInterop()
+ : touchDevice(QTest::createTouchDevice())
+ , touchPointerDevice(QQuickPointerDevice::touchDevice(touchDevice))
+ {}
+
+private slots:
+ void initTestCase();
+
+ void touchDrag();
+ void touchesThenPinch();
+ void unloadHandlerWithPassiveGrab();
+
+private:
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+ QTouchDevice *touchDevice;
+ QQuickPointerDevice *touchPointerDevice;
+};
+
+void tst_MptaInterop::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+{
+ window.reset(new QQuickView);
+ window->setSource(testFileUrl(fileName));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+}
+
+void tst_MptaInterop::initTestCase()
+{
+ // This test assumes that we don't get synthesized mouse events from QGuiApplication
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
+
+ QQmlDataTest::initTestCase();
+}
+
+void tst_MptaInterop::touchDrag()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "pinchDragMPTA.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
+ QVERIFY(mpta);
+ QQuickPinchHandler *pinch = window->rootObject()->findChild<QQuickPinchHandler*>();
+ QVERIFY(pinch);
+ QQuickDragHandler *drag = window->rootObject()->findChild<QQuickDragHandler*>();
+ QVERIFY(drag);
+ QQmlListReference tp(mpta, "touchPoints");
+ QVERIFY(tp.at(3)); // the QML declares four touchpoints
+ QSignalSpy mptaPressedSpy(mpta, SIGNAL(pressed(QList<QObject*>)));
+ QSignalSpy mptaReleasedSpy(mpta, SIGNAL(released(QList<QObject*>)));
+ QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
+
+ // Press one touchpoint:
+ // DragHandler gets a passive grab
+ // PinchHandler declines, because it wants 3 touchpoints
+ // MPTA grabs because DragHandler doesn't accept the single EventPoint
+ QPoint p1 = mpta->mapToScene(QPointF(20, 20)).toPoint();
+ touch.press(1, p1).commit();
+ QQuickTouchUtils::flush(window);
+ auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchPointerDevice);
+ QCOMPARE(tp.at(0)->property("pressed").toBool(), true);
+ QTRY_VERIFY(pointerEvent->point(0)->passiveGrabbers().contains(drag));
+
+ // Start moving
+ // DragHandler keeps monitoring, due to its passive grab,
+ // and eventually steals the exclusive grab from MPTA
+ int dragStoleGrab = 0;
+ for (int i = 0; i < 4; ++i) {
+ p1 += QPoint(dragThreshold / 2, 0);
+ touch.move(1, p1).commit();
+ QQuickTouchUtils::flush(window);
+ if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == drag)
+ dragStoleGrab = i;
+ }
+ if (dragStoleGrab)
+ qCDebug(lcPointerTests, "DragHandler stole the grab after %d events", dragStoleGrab);
+ QVERIFY(dragStoleGrab > 1);
+
+ touch.release(1, p1).commit();
+ QQuickTouchUtils::flush(window);
+}
+
+// TODO touchesThenPinch_data with press/release sequences somehow: vectors of touchpoint IDs? or a string representation?
+void tst_MptaInterop::touchesThenPinch()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "pinchDragMPTA.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
+ QVERIFY(mpta);
+ QQuickPinchHandler *pinch = window->rootObject()->findChild<QQuickPinchHandler*>();
+ QVERIFY(pinch);
+ QQuickDragHandler *drag = window->rootObject()->findChild<QQuickDragHandler*>();
+ QVERIFY(drag);
+ QQmlListReference tp(mpta, "touchPoints");
+ QVERIFY(tp.at(3)); // the QML declares four touchpoints
+ QSignalSpy mptaPressedSpy(mpta, SIGNAL(pressed(QList<QObject*>)));
+ QSignalSpy mptaReleasedSpy(mpta, SIGNAL(released(QList<QObject*>)));
+ QSignalSpy mptaCanceledSpy(mpta, SIGNAL(canceled(QList<QObject*>)));
+ QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
+ auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchPointerDevice);
+
+ // Press one touchpoint:
+ // DragHandler gets a passive grab
+ // PinchHandler declines, because it wants 3 touchpoints
+ // MPTA doesn't get a chance, because DragHandler accepted the single EventPoint
+ QPoint p1 = mpta->mapToScene(QPointF(20, 20)).toPoint();
+ touch.press(1, p1).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
+ QTRY_COMPARE(pointerEvent->point(0)->passiveGrabbers().first(), drag);
+
+ // Press a second touchpoint: MPTA grabs it
+ QPoint p2 = mpta->mapToScene(QPointF(200, 30)).toPoint();
+ touch.stationary(1).press(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+ QVERIFY(tp.at(0)->property("pressed").toBool());
+ QTRY_VERIFY(tp.at(1)->property("pressed").toBool());
+ QCOMPARE(mptaPressedSpy.count(), 2);
+
+ // Press a third touchpoint: MPTA grabs it too
+ QPoint p3 = mpta->mapToScene(QPointF(110, 200)).toPoint();
+ touch.stationary(1).stationary(2).press(3, p3).commit();
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(tp.at(0)->property("pressed").toBool(), true);
+ QCOMPARE(tp.at(1)->property("pressed").toBool(), true);
+ QCOMPARE(tp.at(2)->property("pressed").toBool(), true);
+ QCOMPARE(mptaPressedSpy.count(), 3);
+ QCOMPARE(mptaCanceledSpy.count(), 0);
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
+ QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta);
+ QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta);
+ QVERIFY(!pinch->active());
+
+ // Start moving: PinchHandler steals the exclusive grab from MPTA as soon as dragThreshold is exceeded
+ int pinchStoleGrab = 0;
+
+ const QPointF c = (p1 + p2 + p3)/3; // centroid of p1,p2,p3
+ QTransform xform; // transform to rotate around the centroid
+ xform.translate(c.x(), c.y()).rotate(1).translate(-c.x(), -c.y());
+
+ for (int i = 0; i < 16; ++i) {
+ p1 = xform.map(p1);
+ p2 = xform.map(p2);
+ p3 = xform.map(p3);
+ touch.move(1, p1).move(2, p2).move(3, p3).commit();
+ QQuickTouchUtils::flush(window);
+ if (!pinchStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == pinch) {
+ pinchStoleGrab = i;
+ QCOMPARE(tp.at(0)->property("pressed").toBool(), false);
+ QCOMPARE(tp.at(1)->property("pressed").toBool(), false);
+ QCOMPARE(tp.at(2)->property("pressed").toBool(), false);
+ }
+ }
+ qCDebug(lcPointerTests) << "pinch started after" << pinchStoleGrab << "moves; ended with scale" << pinch->activeScale() << "rot" << pinch->rotation();
+ QTRY_VERIFY(pinch->rotation() > 4);
+ QVERIFY(pinch->activeScale() > 1);
+
+ // Press one more point (pinkie finger)
+ QPoint p4 = mpta->mapToScene(QPointF(300, 200)).toPoint();
+ touch.move(1, p1).move(2, p2).move(3, p3).press(4, p4).commit();
+ // PinchHandler deactivates, which lets MPTA grab all the points
+ QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
+ QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta);
+ QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta);
+ QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta);
+ // Move some more... MPTA keeps reacting
+ for (int i = 0; i < 8; ++i) {
+ p1 += QPoint(4, 4);
+ p2 += QPoint(4, 4);
+ p3 += QPoint(-4, 4);
+ p4 += QPoint(-4, -4);
+ touch.move(1, p1).move(2, p2).move(3, p3).move(4, p4).commit();
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
+ QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta);
+ QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta);
+ QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta);
+ QCOMPARE(tp.at(0)->property("pressed").toBool(), true);
+ QCOMPARE(tp.at(1)->property("pressed").toBool(), true);
+ QCOMPARE(tp.at(2)->property("pressed").toBool(), true);
+ QCOMPARE(tp.at(3)->property("pressed").toBool(), true);
+ }
+
+ // Release the pinkie: PinchHandler acquires passive grabs on the 3 remaining points
+ touch.move(1, p1).move(2, p2).move(3, p3).release(4, p4).commit();
+ // Move some more: PinchHander grabs again, and reacts
+ for (int i = 0; i < 8; ++i) {
+ p1 -= QPoint(4, 4);
+ p2 += QPoint(4, 4);
+ p3 -= QPoint(-4, 4);
+ touch.move(1, p1).move(2, p2).move(3, p3).commit();
+ QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), pinch);
+ QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), pinch);
+ QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), pinch);
+ }
+
+ // Release the first finger
+ touch.stationary(2).stationary(3).release(1, p1).commit();
+ // Move some more: PinchHander isn't interested in a mere 2 points.
+ // MPTA could maybe react; but QQuickWindowPrivate::deliverTouchEvent() calls
+ // deliverPressOrReleaseEvent() in a way which "starts over" with event delivery
+ // only for handlers, not for Items; therefore MPTA is not visited at this time.
+ for (int i = 0; i < 8; ++i) {
+ p2 -= QPoint(4, 4);
+ p3 += QPoint(4, 4);
+ touch.move(2, p2).move(3, p3).commit();
+ QQuickTouchUtils::flush(window);
+ }
+
+ // Release another finger
+ touch.stationary(2).release(3, p3).commit();
+ // Move some more: DragHandler eventually reacts.
+ int dragTookGrab = 0;
+ for (int i = 0; i < 8; ++i) {
+ p2 += QPoint(8, -8);
+ touch.move(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+ QVERIFY(pointerEvent->point(0)->passiveGrabbers().contains(drag));
+ if (!dragTookGrab && pointerEvent->point(0)->exclusiveGrabber() == drag)
+ dragTookGrab = i;
+ }
+ qCDebug(lcPointerTests) << "drag started after" << dragTookGrab << "moves; ended with translation" << drag->translation();
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), drag);
+ QTRY_VERIFY(drag->translation().x() > 0);
+
+ touch.release(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_COMPARE(mptaReleasedSpy.count(), 1);
+}
+
+void tst_MptaInterop::unloadHandlerWithPassiveGrab()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "unloadHandlerOnPress.qml");
+ QQuickView * window = windowPtr.data();
+
+ QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>();
+ QVERIFY(handler);
+ QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
+ QVERIFY(mpta);
+
+ QPoint point(90, 90);
+ QTest::mousePress(window, Qt::LeftButton, 0, point);
+ QCOMPARE(window->mouseGrabberItem(), mpta);
+ QTRY_VERIFY(handler.isNull()); // it got unloaded
+ QTest::mouseRelease(window, Qt::LeftButton, 0, point); // QTBUG-73819: don't crash
+}
+
+QTEST_MAIN(tst_MptaInterop)
+
+#include "tst_multipointtoucharea_interop.moc"
diff --git a/tests/auto/quick/pointerhandlers/pointerhandlers.pro b/tests/auto/quick/pointerhandlers/pointerhandlers.pro
new file mode 100644
index 0000000000..950d6835eb
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/pointerhandlers.pro
@@ -0,0 +1,13 @@
+TEMPLATE = subdirs
+
+qtConfig(private_tests) {
+ SUBDIRS += \
+ flickableinterop \
+ multipointtoucharea_interop \
+ qquickdraghandler \
+ qquickhoverhandler \
+ qquickpinchhandler \
+ qquickpointerhandler \
+ qquickpointhandler \
+ qquicktaphandler \
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
new file mode 100644
index 0000000000..778a799d70
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ objectName: label
+ property int value: 50
+ property int maximumValue: 99
+ property alias label: label.text
+ property alias tapEnabled: tap.enabled
+ property alias pressed: tap.pressed
+ signal tapped
+ width: 140
+ height: 400
+
+ DragHandler {
+ id: dragHandler
+ objectName: label.text + " DragHandler"
+ target: knob
+ xAxis.enabled: false
+ yAxis.minimum: slot.y
+ yAxis.maximum: slot.height + slot.y - knob.height
+ }
+
+ Rectangle {
+ id: slot
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: 10
+ anchors.topMargin: 30
+ anchors.bottomMargin: 30
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 10
+ color: "black"
+ radius: width / 2
+ smooth: true
+ }
+
+ Rectangle {
+ id: glow
+ anchors.fill: knob
+ anchors.margins: -5
+ anchors.leftMargin: -2
+ anchors.horizontalCenterOffset: 1
+ radius: 5
+ color: "#4400FFFF"
+ opacity: tap.pressed || tapFlash.running ? 1 : 0
+ FlashAnimation on visible {
+ id: tapFlash
+ }
+ }
+ Rectangle {
+ id: knob
+ objectName: "Slider Knob"
+ width: parent.width - 2
+ height: 30
+ radius: 5
+ color: "darkgray"
+ border.color: "black"
+ property bool programmatic: false
+ property real multiplier: root.maximumValue / (dragHandler.yAxis.maximum - dragHandler.yAxis.minimum)
+ onYChanged: if (!programmatic) root.value = root.maximumValue - (knob.y - dragHandler.yAxis.minimum) * multiplier
+ transformOrigin: Item.Center
+ function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier }
+ TapHandler {
+ id: tap
+ objectName: label.text + " TapHandler"
+ gesturePolicy: TapHandler.DragThreshold
+ onTapped: {
+ tapFlash.start()
+ root.tapped
+ }
+ }
+ }
+
+ Text {
+ font.pointSize: 16
+ color: "red"
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: root.value
+ }
+
+ Text {
+ id: label
+ font.pointSize: 12
+ color: "red"
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ Component.onCompleted: {
+ knob.programmatic = true
+ knob.setValue(root.value)
+ knob.programmatic = false
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
new file mode 100644
index 0000000000..158a02b7a6
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+SequentialAnimation {
+ id: tapFlash
+ running: false
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
new file mode 100644
index 0000000000..782750b783
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ objectName: label
+ property int value: 50
+ property int maximumValue: 99
+ property alias label: label.text
+ property alias tapEnabled: tap.enabled
+ property alias pressed: tap.pressed
+ signal tapped
+ width: 140
+ height: 400
+
+ Rectangle {
+ id: slot
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: 10
+ anchors.topMargin: 30
+ anchors.bottomMargin: 30
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 10
+ color: "black"
+ radius: width / 2
+ smooth: true
+ }
+
+ Rectangle {
+ id: glow
+ anchors.fill: knob
+ anchors.margins: -5
+ anchors.leftMargin: -2
+ anchors.horizontalCenterOffset: 1
+ radius: 5
+ color: "#4400FFFF"
+ opacity: tap.pressed || tapFlash.running ? 1 : 0
+ FlashAnimation on visible {
+ id: tapFlash
+ }
+ }
+ Rectangle {
+ id: knob
+ objectName: root.label + " Knob"
+ width: parent.width - 2
+ height: 30
+ radius: 5
+ color: "darkgray"
+ border.color: "black"
+ property bool programmatic: false
+ property real multiplier: root.maximumValue / (dragHandler.yAxis.maximum - dragHandler.yAxis.minimum)
+ onYChanged: if (!programmatic) root.value = root.maximumValue - (knob.y - dragHandler.yAxis.minimum) * multiplier
+ transformOrigin: Item.Center
+ function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier }
+ function flash() { tapFlash.start() }
+ DragHandler {
+ id: dragHandler
+ objectName: label.text + " DragHandler"
+ xAxis.enabled: false
+ yAxis.minimum: slot.y
+ yAxis.maximum: slot.height + slot.y - knob.height
+ }
+ TapHandler {
+ id: tap
+ objectName: label.text + " TapHandler"
+ gesturePolicy: TapHandler.DragThreshold
+ onTapped: {
+ tapFlash.start()
+ root.tapped
+ }
+ }
+ }
+
+ Text {
+ font.pointSize: 16
+ color: "red"
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: root.value
+ }
+
+ Text {
+ id: label
+ font.pointSize: 12
+ color: "red"
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ Component.onCompleted: {
+ knob.programmatic = true
+ knob.setValue(root.value)
+ knob.programmatic = false
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
new file mode 100644
index 0000000000..7b3601bea0
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ objectName: "Draggables"
+ width: 640
+ height: 480
+
+ Repeater {
+ model: 2
+
+ Rectangle {
+ id: ball
+ objectName: "Ball " + (index + 1)
+ color: dragHandler.active ? "blue" : "lightsteelblue"
+ width: 80; height: 80; x: 200 + index * 200; y: 200; radius: width / 2
+ onParentChanged: console.log(this + " parent " + parent)
+
+ DragHandler {
+ id: dragHandler
+ objectName: "DragHandler " + (index + 1)
+ }
+
+ Text {
+ color: "white"
+ anchors.centerIn: parent
+ horizontalAlignment: Text.AlignHCenter
+ text: ball.objectName + "\n" + dragHandler.centroid.position.x.toFixed(1) + "," + dragHandler.centroid.position.y.toFixed(1)
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
new file mode 100644
index 0000000000..08b85aef50
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draghandler_and_pinchhandler.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ objectName: "DragHandler_and_PinchHandler"
+ width: 640
+ height: 480
+
+ Rectangle {
+ id: rect
+ objectName: "Rect"
+ color: dragHandler.active ? "blue" : (pinchHandler.active ? "magenta" : "grey")
+ width: 200; height: 200; x: 100; y: 100
+
+ PinchHandler {
+ id: pinchHandler
+ objectName: "PinchHandler"
+ }
+ DragHandler {
+ id: dragHandler
+ objectName: "DragHandler"
+ }
+
+ Text {
+ color: "white"
+ anchors.centerIn: parent
+ horizontalAlignment: Text.AlignHCenter
+ text: rect.objectName + "\n"
+ + "rotation:" + rect.rotation + "\n"
+ + dragHandler.centroid.position.x.toFixed(1) + "," + dragHandler.centroid.position.y.toFixed(1)
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
new file mode 100644
index 0000000000..f6042f4461
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ width: 900
+ height: 850
+ objectName: "root"
+ color: "#222222"
+
+ Grid {
+ objectName: "grid"
+ anchors.fill: parent
+ spacing: 10
+ columns: 6
+ Repeater {
+ id: top
+ objectName: "top"
+ model: 6
+
+ delegate: Slider {
+ objectName: label
+ label: "Drag Knob " + index
+ width: 140
+ }
+ }
+ Repeater {
+ id: bottom
+ objectName: "bottom"
+ model: 6
+
+ delegate: DragAnywhereSlider {
+ objectName: label
+ label: "Drag Anywhere " + index
+ width: 140
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/reparenting.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/reparenting.qml
new file mode 100644
index 0000000000..e23cddf7a6
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/reparenting.qml
@@ -0,0 +1,59 @@
+import QtQuick 2.12
+
+Grid {
+ id: root
+ objectName: "root"
+ property bool reparentOnDrag: true
+ width: 200; height: 200
+ columns: 3
+ spacing: 10
+ Repeater {
+ model: 9
+ anchors.fill: parent
+ Item {
+ id: gridPlaceholder
+ objectName: "gridPlaceholder" + index
+ width: 60
+ height: 60
+ Rectangle {
+ id: icon
+ border.color: "black"
+ color: "beige"
+ radius: 3
+ width: 60
+ height: 60
+ onParentChanged :console.log("parent " + parent)
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
+ DragHandler {
+ id: dragArea
+ }
+ Text {
+ anchors.centerIn: parent
+ text: index + "@" + Math.round(icon.x) + "," + Math.round(icon.y)
+ font.pointSize: 8
+ }
+ states: [
+ State {
+ when: dragArea.dragging
+ AnchorChanges {
+ target: icon
+ anchors.horizontalCenter: undefined
+ anchors.verticalCenter: undefined
+ }
+ ParentChange {
+ target: root.reparentOnDrag ? icon : null
+ parent: root
+ }
+ PropertyChanges {
+ target: icon
+ color: "yellow"
+ }
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml
new file mode 100644
index 0000000000..6e5574787c
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ width: 900
+ height: 850
+ objectName: "root"
+ color: "#222222"
+
+ Row {
+ objectName: "row"
+ anchors.fill: parent
+ spacing: 10
+ Rectangle {
+ width: 50
+ height: 50
+ color: "aqua"
+ objectName: "dragAndTap"
+ DragHandler {
+ objectName: "drag"
+ }
+ TapHandler {
+ objectName: "tap"
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ }
+ Rectangle {
+ width: 50
+ height: 50
+ color: "aqua"
+ objectName: "tapAndDrag"
+ TapHandler {
+ objectName: "tap"
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ DragHandler {
+ objectName: "drag"
+ }
+ }
+
+ Rectangle {
+ color: "aqua"
+ width: 50
+ height: 50
+ objectName: "dragAndTapNotSiblings"
+ DragHandler {
+ objectName: "drag"
+ }
+ Rectangle {
+ color: "blue"
+ width: 30
+ height: 30
+ anchors.centerIn: parent
+ TapHandler {
+ objectName: "tap"
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ }
+ }
+ Rectangle {
+ color: "aqua"
+ width: 50
+ height: 50
+ objectName: "tapAndDragNotSiblings"
+ TapHandler {
+ objectName: "tap"
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ Rectangle {
+ color: "blue"
+ x: 10
+ y: 10
+ width: 30
+ height: 30
+ DragHandler {
+ objectName: "drag"
+ }
+ }
+ }
+
+
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro b/tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro
new file mode 100644
index 0000000000..42c4e46c4f
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro
@@ -0,0 +1,21 @@
+CONFIG += testcase
+
+TARGET = tst_qquickdraghandler
+QT += core-private gui-private qml-private quick-private testlib
+
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qquickdraghandler.cpp
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/DragAnywhereSlider.qml \
+ data/FlashAnimation.qml \
+ data/Slider.qml \
+ data/draggables.qml \
+ data/grabberstate.qml \
+ data/multipleSliders.qml \
+ data/reparenting.qml \
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
new file mode 100644
index 0000000000..eb210c2112
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -0,0 +1,573 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlproperty.h>
+#include <QtQuick/private/qquickdraghandler_p.h>
+#include <QtQuick/private/qquickrepeater_p.h>
+#include <QtQuick/private/qquicktaphandler_p.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
+
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+class tst_DragHandler : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_DragHandler()
+ :touchDevice(QTest::createTouchDevice())
+ {}
+
+private slots:
+ void initTestCase();
+
+ void defaultPropertyValues();
+ void touchDrag();
+ void mouseDrag();
+ void touchDragMulti();
+ void touchDragMultiSliders_data();
+ void touchDragMultiSliders();
+ void touchPassiveGrabbers_data();
+ void touchPassiveGrabbers();
+ void touchPinchAndMouseMove();
+
+private:
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+ QSet<QQuickPointerHandler *> passiveGrabbers(QQuickWindow *window, int pointId = 0);
+ QTouchDevice *touchDevice;
+};
+
+void tst_DragHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+{
+ window.reset(new QQuickView);
+ window->setSource(testFileUrl(fileName));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+}
+
+QSet<QQuickPointerHandler*> tst_DragHandler::passiveGrabbers(QQuickWindow *window, int pointId /*= 0*/)
+{
+ QSet<QQuickPointerHandler*> result;
+ QQuickWindowPrivate *winp = QQuickWindowPrivate::get(window);
+ if (QQuickPointerDevice* device = QQuickPointerDevice::touchDevice(touchDevice)) {
+ QQuickPointerEvent *pointerEvent = winp->pointerEventInstance(device);
+ for (int i = 0; i < pointerEvent->pointCount(); ++i) {
+ QQuickEventPoint *eventPoint = pointerEvent->point(i);
+ QVector<QPointer <QQuickPointerHandler> > passives = eventPoint->passiveGrabbers();
+ if (!pointId || eventPoint->pointId() == pointId) {
+ for (auto it = passives.constBegin(); it != passives.constEnd(); ++it)
+ result << it->data();
+ }
+ }
+ }
+ return result;
+}
+
+void tst_DragHandler::initTestCase()
+{
+ // This test assumes that we don't get synthesized mouse events from QGuiApplication
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
+
+ QQmlDataTest::initTestCase();
+}
+
+void tst_DragHandler::defaultPropertyValues()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "draggables.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *ball = window->rootObject()->childItems().first();
+ QVERIFY(ball);
+ QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler);
+
+ QCOMPARE(dragHandler->acceptedButtons(), Qt::LeftButton);
+ QCOMPARE(dragHandler->translation(), QVector2D());
+ QCOMPARE(dragHandler->centroid().position(), QPointF());
+ QCOMPARE(dragHandler->centroid().scenePosition(), QPointF());
+ QCOMPARE(dragHandler->centroid().pressPosition(), QPointF());
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), QPointF());
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), QPointF());
+}
+
+void tst_DragHandler::touchDrag()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "draggables.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *ball = window->rootObject()->childItems().first();
+ QVERIFY(ball);
+ QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler);
+
+ QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
+ QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
+
+ QPointF ballCenter = ball->clipRect().center();
+ QPointF scenePressPos = ball->mapToScene(ballCenter);
+ QPoint p1 = scenePressPos.toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
+ QCOMPARE(centroidChangedSpy.count(), 1);
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 2);
+ QVERIFY(!dragHandler->active());
+ p1 += QPoint(1, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(translationChangedSpy.count(), 0);
+ QCOMPARE(centroidChangedSpy.count(), 3);
+ QCOMPARE(dragHandler->translation().x(), 0.0);
+ QPointF sceneGrabPos = p1;
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ p1 += QPoint(19, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler->translation().y(), 0.0);
+ QVERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 4);
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
+ QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
+ QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
+ QCOMPARE(translationChangedSpy.count(), 1);
+ QCOMPARE(centroidChangedSpy.count(), 5);
+}
+
+void tst_DragHandler::mouseDrag()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "draggables.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *ball = window->rootObject()->childItems().first();
+ QVERIFY(ball);
+ QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler);
+
+ QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
+ QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
+
+ QPointF ballCenter = ball->clipRect().center();
+ QPointF scenePressPos = ball->mapToScene(ballCenter);
+ QPoint p1 = scenePressPos.toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
+ QCOMPARE(centroidChangedSpy.count(), 1);
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 2);
+ QVERIFY(!dragHandler->active());
+ p1 += QPoint(1, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(translationChangedSpy.count(), 0);
+ QCOMPARE(centroidChangedSpy.count(), 3);
+ QCOMPARE(dragHandler->translation().x(), 0.0);
+ QPointF sceneGrabPos = p1;
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ p1 += QPoint(19, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler->translation().y(), 0.0);
+ QVERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 4);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
+ QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
+ QCOMPARE(translationChangedSpy.count(), 1);
+ QCOMPARE(centroidChangedSpy.count(), 5);
+}
+
+void tst_DragHandler::touchDragMulti()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "draggables.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *ball1 = window->rootObject()->childItems().first();
+ QVERIFY(ball1);
+ QQuickDragHandler *dragHandler1 = ball1->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler1);
+ QSignalSpy translationChangedSpy1(dragHandler1, SIGNAL(translationChanged()));
+ QSignalSpy centroidChangedSpy1(dragHandler1, SIGNAL(centroidChanged()));
+
+ QQuickItem *ball2 = window->rootObject()->childItems().at(1);
+ QVERIFY(ball2);
+ QQuickDragHandler *dragHandler2 = ball2->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler2);
+ QSignalSpy translationChangedSpy2(dragHandler2, SIGNAL(translationChanged()));
+ QSignalSpy centroidChangedSpy2(dragHandler1, SIGNAL(centroidChanged()));
+
+ QPointF ball1Center = ball1->clipRect().center();
+ QPointF scenePressPos1 = ball1->mapToScene(ball1Center);
+ QPoint p1 = scenePressPos1.toPoint();
+ QPointF ball2Center = ball2->clipRect().center();
+ QPointF scenePressPos2 = ball2->mapToScene(ball2Center);
+ QPoint p2 = scenePressPos2.toPoint();
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
+
+ touchSeq.press(1, p1, window).press(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!dragHandler1->active());
+ QCOMPARE(centroidChangedSpy1.count(), 1);
+ QCOMPARE(dragHandler1->centroid().position(), ball1Center);
+ QCOMPARE(dragHandler1->centroid().pressPosition(), ball1Center);
+ QCOMPARE(dragHandler1->centroid().scenePosition(), scenePressPos1);
+ QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1);
+ QVERIFY(!dragHandler2->active());
+ QCOMPARE(centroidChangedSpy2.count(), 1);
+ QCOMPARE(dragHandler2->centroid().position(), ball2Center);
+ QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center);
+ QCOMPARE(dragHandler2->centroid().scenePosition(), scenePressPos2);
+ QCOMPARE(dragHandler2->centroid().scenePressPosition(), scenePressPos2);
+ p1 += QPoint(dragThreshold, 0);
+ p2 += QPoint(0, dragThreshold);
+ touchSeq.move(1, p1, window).move(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!dragHandler1->active());
+ QCOMPARE(centroidChangedSpy1.count(), 2);
+ QCOMPARE(dragHandler1->centroid().position(), ball1Center + QPointF(dragThreshold, 0));
+ QCOMPARE(dragHandler1->centroid().pressPosition(), ball1Center);
+ QCOMPARE(dragHandler1->centroid().scenePosition().toPoint(), p1);
+ QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1);
+ QVERIFY(!dragHandler2->active());
+ QCOMPARE(centroidChangedSpy2.count(), 2);
+ QCOMPARE(dragHandler2->centroid().position(), ball2Center + QPointF(0, dragThreshold));
+ QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center);
+ QCOMPARE(dragHandler2->centroid().scenePosition().toPoint(), p2);
+ QCOMPARE(dragHandler2->centroid().scenePressPosition(), scenePressPos2);
+ p1 += QPoint(1, 0);
+ p2 += QPoint(0, 1);
+ touchSeq.move(1, p1, window).move(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(dragHandler1->active());
+ QVERIFY(dragHandler2->active());
+ QCOMPARE(translationChangedSpy1.count(), 0);
+ QCOMPARE(dragHandler1->translation().x(), 0.0);
+ QPointF sceneGrabPos1 = p1;
+ QPointF sceneGrabPos2 = p2;
+ QCOMPARE(dragHandler1->centroid().sceneGrabPosition(), sceneGrabPos1);
+ QCOMPARE(dragHandler2->centroid().sceneGrabPosition(), sceneGrabPos2);
+ p1 += QPoint(19, 0);
+ p2 += QPoint(0, 19);
+ QVERIFY(dragHandler2->active());
+ QCOMPARE(translationChangedSpy2.count(), 0);
+ QCOMPARE(dragHandler2->translation().x(), 0.0);
+ QCOMPARE(dragHandler2->centroid().sceneGrabPosition(), sceneGrabPos2);
+ touchSeq.move(1, p1, window).move(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ QVERIFY(dragHandler1->active());
+ QVERIFY(dragHandler2->active());
+ QCOMPARE(dragHandler1->centroid().position(), ball1Center);
+ QCOMPARE(dragHandler1->centroid().pressPosition(), ball1Center);
+ QCOMPARE(dragHandler1->centroid().scenePosition(), ball1->mapToScene(ball1Center));
+ QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1);
+ QCOMPARE(dragHandler1->centroid().sceneGrabPosition(), sceneGrabPos1);
+ QCOMPARE(dragHandler1->translation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler1->translation().y(), 0.0);
+ QCOMPARE(dragHandler2->centroid().position(), ball2Center);
+ QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center);
+ QCOMPARE(dragHandler2->centroid().scenePosition(), ball2->mapToScene(ball2Center));
+ QCOMPARE(dragHandler2->centroid().scenePressPosition(), scenePressPos2);
+ QCOMPARE(dragHandler2->centroid().sceneGrabPosition(), sceneGrabPos2);
+ QCOMPARE(dragHandler2->translation().x(), 0.0);
+ QCOMPARE(dragHandler2->translation().y(), dragThreshold + 20.0);
+ touchSeq.release(1, p1, window).stationary(2).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!dragHandler1->active());
+ QVERIFY(dragHandler2->active());
+ QCOMPARE(dragHandler1->centroid().pressedButtons(), Qt::NoButton);
+ QCOMPARE(ball1->mapToScene(ball1Center).toPoint(), p1);
+ QCOMPARE(translationChangedSpy1.count(), 1);
+ touchSeq.release(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!dragHandler2->active());
+ QCOMPARE(ball2->mapToScene(ball2Center).toPoint(), p2);
+ QCOMPARE(translationChangedSpy2.count(), 1);
+}
+
+void tst_DragHandler::touchDragMultiSliders_data()
+{
+ QTest::addColumn<int>("sliderRow");
+ QTest::addColumn<QVector<int> >("whichSliders");
+ QTest::addColumn<QVector<int> >("startingCenterOffsets");
+ QTest::addColumn<QVector<QVector2D> >("movements");
+
+ QTest::newRow("Drag Knob: start on the knobs, drag down") <<
+ 0 << QVector<int> { 0, 1, 2 } << QVector<int> { 0, 0, 0 } << QVector<QVector2D> { {0, 60}, {0, 60}, {0, 60} };
+ QTest::newRow("Drag Knob: start on the knobs, drag diagonally downward") <<
+ 0 << QVector<int> { 0, 1, 2 } << QVector<int> { 0, 0, 0 } << QVector<QVector2D> { {20, 40}, {20, 60}, {20, 80} };
+ QTest::newRow("Drag Anywhere: start on the knobs, drag down") <<
+ 1 << QVector<int> { 0, 1, 2 } << QVector<int> { 0, 0, 0 } << QVector<QVector2D> { {0, 60}, {0, 60}, {0, 60} };
+ QTest::newRow("Drag Anywhere: start on the knobs, drag diagonally downward") <<
+ 1 << QVector<int> { 0, 1, 2 } << QVector<int> { 0, 0, 0 } << QVector<QVector2D> { {20, 40}, {20, 60}, {20, 80} };
+ // TODO these next two fail because the DragHandler grabs when a finger
+ // drags across it from outside, but should rather start only if it is pressed inside
+// QTest::newRow("Drag Knob: start above the knobs, drag down") <<
+// 0 << QVector<int> { 0, 1, 2 } << QVector<int> { -30, -30, -30 } << QVector<QVector2D> { {0, 40}, {0, 60}, {0, 80} };
+// QTest::newRow("Drag Knob: start above the knobs, drag diagonally downward") <<
+// 0 << QVector<int> { 0, 1, 2 } << QVector<int> { -30, -30, -30 } << QVector<QVector2D> { {20, 40}, {20, 60}, {20, 80} };
+ QTest::newRow("Drag Anywhere: start above the knobs, drag down") <<
+ 1 << QVector<int> { 0, 1, 2 } << QVector<int> { -20, -30, -40 } << QVector<QVector2D> { {0, 60}, {0, 60}, {0, 60} };
+ QTest::newRow("Drag Anywhere: start above the knobs, drag diagonally downward") <<
+ 1 << QVector<int> { 0, 1, 2 } << QVector<int> { -20, -30, -40 } << QVector<QVector2D> { {20, 40}, {20, 60}, {20, 80} };
+}
+
+void tst_DragHandler::touchDragMultiSliders()
+{
+ QFETCH(int, sliderRow);
+ QFETCH(QVector<int>, whichSliders);
+ QFETCH(QVector<int>, startingCenterOffsets);
+ QFETCH(QVector<QVector2D>, movements);
+ const int moveCount = 8;
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "multipleSliders.qml");
+ QQuickView * window = windowPtr.data();
+ QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
+
+ QQuickRepeater *rowRepeater = window->rootObject()->findChildren<QQuickRepeater *>()[sliderRow];
+ QVector<QQuickItem *> knobs;
+ QVector<QQuickDragHandler *> dragHandlers;
+ QVector<QQuickTapHandler *> tapHandlers;
+ QVector<QPointF> startPoints;
+ for (int sli : whichSliders) {
+ QQuickItem *slider = rowRepeater->itemAt(sli);
+ QVERIFY(slider);
+ dragHandlers << slider->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandlers[sli]);
+ tapHandlers << slider->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandlers[sli]);
+ knobs << tapHandlers[sli]->parentItem();
+ QPointF startPoint = knobs[sli]->mapToScene(knobs[sli]->clipRect().center());
+ startPoint.setY(startPoint.y() + startingCenterOffsets[sli]);
+ startPoints << startPoint;
+ qCDebug(lcPointerTests) << "row" << sliderRow << "slider" << sli << slider->objectName() <<
+ "start" << startingCenterOffsets[sli] << startPoints[sli];
+ }
+ QVector<QPointF> touchPoints = startPoints;
+
+ // Press
+ for (int sli : whichSliders)
+ touch.press(sli, touchPoints[sli].toPoint());
+ touch.commit();
+
+ // Moves
+ for (int m = 0; m < moveCount; ++m) {
+ for (int sli : whichSliders) {
+ QVector2D incr = movements[sli] / moveCount;
+ touchPoints[sli] += incr.toPointF();
+ touch.move(sli, touchPoints[sli].toPoint());
+ }
+ touch.commit();
+ QQuickTouchUtils::flush(window);
+ }
+
+ // Check that they moved to where they should: since the slider is constrained,
+ // only the y component should have an effect; knobs should not come out of their "grooves"
+ for (int sli : whichSliders) {
+ QPoint endPosition = knobs[sli]->mapToScene(knobs[sli]->clipRect().center()).toPoint();
+ QPoint expectedEndPosition(startPoints[sli].x(), startPoints[sli].y() + movements[sli].y());
+ if (sliderRow == 0 && qAbs(startingCenterOffsets[sli]) > knobs[sli]->height() / 2)
+ expectedEndPosition = startPoints[sli].toPoint();
+ qCDebug(lcPointerTests) << "slider " << knobs[sli]->objectName() << "started @" << startPoints[sli]
+ << "tried to move by" << movements[sli] << "ended up @" << endPosition << "expected" << expectedEndPosition;
+ QTRY_COMPARE(endPosition, expectedEndPosition);
+ }
+
+ // Release
+ for (int sli : whichSliders)
+ touch.release(sli, touchPoints[sli].toPoint());
+ touch.commit();
+}
+
+void tst_DragHandler::touchPassiveGrabbers_data()
+{
+ QTest::addColumn<QString>("itemName");
+ QTest::addColumn<QStringList>("expectedPassiveGrabberNames");
+
+ QTest::newRow("Drag And Tap") << "dragAndTap" << QStringList({"drag", "tap"});
+ QTest::newRow("Tap And Drag") << "tapAndDrag" << QStringList({"tap", "drag"});
+ QTest::newRow("Drag And Tap (not siblings)") << "dragAndTapNotSiblings" << QStringList({"drag", "tap"});
+ QTest::newRow("Tap And Drag (not siblings)") << "tapAndDragNotSiblings" << QStringList({"tap", "drag"});
+}
+
+void tst_DragHandler::touchPassiveGrabbers()
+{
+ QFETCH(QString, itemName);
+ QFETCH(QStringList, expectedPassiveGrabberNames);
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "simpleTapAndDragHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *row2 = window->rootObject()->findChild<QQuickItem*>(itemName);
+ QSet<QQuickPointerHandler *> expectedPassiveGrabbers;
+ for (QString objectName : expectedPassiveGrabberNames)
+ expectedPassiveGrabbers << row2->findChild<QQuickPointerHandler*>(objectName);
+
+ QPointF p1 = row2->mapToScene(row2->clipRect().center());
+ QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
+ touch.press(1, p1.toPoint()).commit();
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(passiveGrabbers(window), expectedPassiveGrabbers);
+
+ QQuickDragHandler *dragHandler = nullptr;
+ for (QQuickPointerHandler *handler: expectedPassiveGrabbers) {
+ QPointF scenePressPos;
+ if (QQuickMultiPointHandler *mph = qmlobject_cast<QQuickMultiPointHandler *>(handler))
+ scenePressPos = mph->centroid().scenePressPosition();
+ else
+ scenePressPos = static_cast<QQuickSinglePointHandler *>(handler)->point().scenePressPosition();
+ QCOMPARE(scenePressPos, p1);
+ QQuickDragHandler *dh = qmlobject_cast<QQuickDragHandler *>(handler);
+ if (dh)
+ dragHandler = dh;
+ }
+ QVERIFY(dragHandler);
+ QPointF initialPos = dragHandler->target()->position();
+
+ p1 += QPointF(50, 50);
+ touch.move(1, p1.toPoint()).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(dragHandler->active());
+
+ p1 += QPointF(50, 50);
+ touch.move(1, p1.toPoint()).commit();
+ QQuickTouchUtils::flush(window);
+ QPointF movementDelta = dragHandler->target()->position() - initialPos;
+ qCDebug(lcPointerTests) << "DragHandler moved the target by" << movementDelta;
+ QVERIFY(movementDelta.x() >= 100);
+ QVERIFY(movementDelta.y() >= 100);
+
+ QTest::qWait(500);
+
+ touch.release(1, p1.toPoint());
+ touch.commit();
+ QQuickTouchUtils::flush(window);
+}
+
+void tst_DragHandler::touchPinchAndMouseMove()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "draghandler_and_pinchhandler.qml");
+ QQuickView *window = windowPtr.data();
+ QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>(QLatin1String("Rect"));
+ QQuickPointerHandler *pinchHandler = window->rootObject()->findChild<QQuickPointerHandler*>(QLatin1String("PinchHandler"));
+
+ QPoint p1(150,200);
+ QPoint p2(250,200);
+
+ // Trigger a scale pinch, PinchHandler should activate
+ QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
+ touch.press(1, p1).press(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+ QPoint delta(10,0);
+ for (int i = 0; i < 10 && !pinchHandler->active(); ++i) {
+ p1-=delta;
+ p2+=delta;
+ touch.move(1, p1).move(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(pinchHandler->active(), true);
+
+ // While having the touch points pressed, send wrong mouse event as MS Windows did:
+ // * A MoveMove with LeftButton down
+ // (in order to synthesize that, qtestMouseButtons needs to be modified)
+ // (This will make the DragHandler do a passive grab)
+ QTestPrivate::qtestMouseButtons = Qt::LeftButton;
+ QTest::mouseMove(window, p1 + delta);
+
+ touch.release(1, p1).release(2, p2).commit();
+ QQuickTouchUtils::flush(window);
+
+ // Now move the mouse with no buttons down and check if the rect did not move
+ // At this point, no touch points are pressed and no mouse buttons are pressed.
+ QTestPrivate::qtestMouseButtons = Qt::NoButton;
+ QSignalSpy rectMovedSpy(rect, SIGNAL(xChanged()));
+ for (int i = 0; i < 10; ++i) {
+ p1 += delta;
+ QTest::mouseMove(window, p1);
+ QCOMPARE(rectMovedSpy.count(), 0);
+ }
+}
+
+QTEST_MAIN(tst_DragHandler)
+
+#include "tst_qquickdraghandler.moc"
+
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
new file mode 100644
index 0000000000..011dc4e75f
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/lesHoverables.qml
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ width: 640
+ height: 480
+ color: "#444"
+
+ Component {
+ id: buttonsAndStuff
+ Column {
+ anchors.fill: parent
+ anchors.margins: 8
+ spacing: 8
+
+ Rectangle {
+ objectName: "buttonWithMA"
+ width: parent.width
+ height: 30
+ color: buttonMA.pressed ? "lightsteelblue" : "#999"
+ border.color: buttonMA.containsMouse ? "cyan" : "transparent"
+
+ MouseArea {
+ id: buttonMA
+ objectName: "buttonMA"
+ hoverEnabled: true
+ anchors.fill: parent
+ onClicked: console.log("clicked MA")
+ }
+
+ Text {
+ anchors.centerIn: parent
+ text: "MouseArea"
+ }
+ }
+
+ Rectangle {
+ objectName: "buttonWithHH"
+ width: parent.width
+ height: 30
+ color: flash ? "#999" : "white"
+ border.color: buttonHH.hovered ? "cyan" : "transparent"
+ property bool flash: true
+
+ HoverHandler {
+ id: buttonHH
+ objectName: "buttonHH"
+ acceptedDevices: PointerDevice.AllDevices
+ }
+
+ TapHandler { }
+
+ Text {
+ anchors.centerIn: parent
+ text: "HoverHandler"
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: paddle
+ objectName: "paddle"
+ width: 100
+ height: 100
+ color: paddleHH.hovered ? "indianred" : "#888"
+ x: (parent.width - width) / 2
+ y: parent.height - 100
+ radius: 10
+
+ HoverHandler {
+ id: paddleHH
+ objectName: "paddleHH"
+ }
+ }
+
+ Rectangle {
+ objectName: "topSidebar"
+ radius: 5
+ antialiasing: true
+ x: -radius
+ y: -radius
+ width: 120
+ height: 200
+ border.color: topSidebarHH.hovered ? "cyan" : "black"
+ color: "#777"
+
+ Rectangle {
+ color: "cyan"
+ width: 10
+ height: width
+ radius: width / 2
+ visible: topSidebarHH.hovered
+ x: topSidebarHH.point.position.x - width / 2
+ y: topSidebarHH.point.position.y - height / 2
+ z: 100
+ }
+
+ HoverHandler {
+ id: topSidebarHH
+ objectName: "topSidebarHH"
+ }
+
+ Loader {
+ objectName: "topSidebarLoader"
+ sourceComponent: buttonsAndStuff
+ anchors.fill: parent
+ }
+ }
+
+ Rectangle {
+ objectName: "bottomSidebar"
+ radius: 5
+ antialiasing: true
+ x: -radius
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: -radius
+ width: 120
+ height: 200
+ border.color: bottomSidebarMA.containsMouse ? "cyan" : "black"
+ color: "#777"
+
+ MouseArea {
+ id: bottomSidebarMA
+ objectName: "bottomSidebarMA"
+ hoverEnabled: true
+ anchors.fill: parent
+ }
+
+ Loader {
+ objectName: "bottomSidebarLoader"
+ sourceComponent: buttonsAndStuff
+ anchors.fill: parent
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/qquickhoverhandler.pro b/tests/auto/quick/pointerhandlers/qquickhoverhandler/qquickhoverhandler.pro
new file mode 100644
index 0000000000..34633e2532
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/qquickhoverhandler.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+
+TARGET = tst_qquickhoverhandler
+QT += core-private gui-private qml-private quick-private testlib
+
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qquickhoverhandler.cpp
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/lesHoverables.qml \
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
new file mode 100644
index 0000000000..f141a2546c
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtQuick/qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickhoverhandler_p.h>
+#include <QtQuick/private/qquickmousearea_p.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <private/qquickwindow_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlproperty.h>
+
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+static bool isPlatformWayland()
+{
+ return !QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive);
+}
+
+class tst_HoverHandler : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_HoverHandler()
+ {}
+
+private slots:
+ void hoverHandlerAndUnderlyingHoverHandler();
+ void mouseAreaAndUnderlyingHoverHandler();
+ void hoverHandlerAndUnderlyingMouseArea();
+ void movingItemWithHoverHandler();
+
+private:
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+};
+
+void tst_HoverHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+{
+ window.reset(new QQuickView);
+ window->setSource(testFileUrl(fileName));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+}
+
+void tst_HoverHandler::hoverHandlerAndUnderlyingHoverHandler()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "lesHoverables.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem * topSidebar = window->rootObject()->findChild<QQuickItem *>("topSidebar");
+ QVERIFY(topSidebar);
+ QQuickItem * button = topSidebar->findChild<QQuickItem *>("buttonWithHH");
+ QVERIFY(button);
+ QQuickHoverHandler *topSidebarHH = topSidebar->findChild<QQuickHoverHandler *>("topSidebarHH");
+ QVERIFY(topSidebarHH);
+ QQuickHoverHandler *buttonHH = button->findChild<QQuickHoverHandler *>("buttonHH");
+ QVERIFY(buttonHH);
+
+ QPoint buttonCenter(button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint());
+ QPoint rightOfButton(button->mapToScene(QPointF(button->width() + 2, button->height() / 2)).toPoint());
+ QPoint outOfSidebar(topSidebar->mapToScene(QPointF(topSidebar->width() + 2, topSidebar->height() / 2)).toPoint());
+ QSignalSpy sidebarHoveredSpy(topSidebarHH, SIGNAL(hoveredChanged()));
+ QSignalSpy buttonHoveredSpy(buttonHH, SIGNAL(hoveredChanged()));
+
+ QTest::mouseMove(window, outOfSidebar);
+ QCOMPARE(topSidebarHH->isHovered(), false);
+ QCOMPARE(sidebarHoveredSpy.count(), 0);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 0);
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(topSidebarHH->isHovered(), true);
+ QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 0);
+
+ QTest::mouseMove(window, buttonCenter);
+ QCOMPARE(topSidebarHH->isHovered(), true);
+ QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(buttonHH->isHovered(), true);
+ QCOMPARE(buttonHoveredSpy.count(), 1);
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(topSidebarHH->isHovered(), true);
+ QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 2);
+
+ QTest::mouseMove(window, outOfSidebar);
+ QCOMPARE(topSidebarHH->isHovered(), false);
+ QCOMPARE(sidebarHoveredSpy.count(), 2);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 2);
+}
+
+void tst_HoverHandler::mouseAreaAndUnderlyingHoverHandler()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "lesHoverables.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem * topSidebar = window->rootObject()->findChild<QQuickItem *>("topSidebar");
+ QVERIFY(topSidebar);
+ QQuickMouseArea * buttonMA = topSidebar->findChild<QQuickMouseArea *>("buttonMA");
+ QVERIFY(buttonMA);
+ QQuickHoverHandler *topSidebarHH = topSidebar->findChild<QQuickHoverHandler *>("topSidebarHH");
+ QVERIFY(topSidebarHH);
+
+ QPoint buttonCenter(buttonMA->mapToScene(QPointF(buttonMA->width() / 2, buttonMA->height() / 2)).toPoint());
+ QPoint rightOfButton(buttonMA->mapToScene(QPointF(buttonMA->width() + 2, buttonMA->height() / 2)).toPoint());
+ QPoint outOfSidebar(topSidebar->mapToScene(QPointF(topSidebar->width() + 2, topSidebar->height() / 2)).toPoint());
+ QSignalSpy sidebarHoveredSpy(topSidebarHH, SIGNAL(hoveredChanged()));
+ QSignalSpy buttonHoveredSpy(buttonMA, SIGNAL(hoveredChanged()));
+
+ QTest::mouseMove(window, outOfSidebar);
+ QCOMPARE(topSidebarHH->isHovered(), false);
+ QCOMPARE(sidebarHoveredSpy.count(), 0);
+ QCOMPARE(buttonMA->hovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 0);
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(topSidebarHH->isHovered(), true);
+ QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(buttonMA->hovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 0);
+
+ QTest::mouseMove(window, buttonCenter);
+ QCOMPARE(topSidebarHH->isHovered(), true);
+ QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(buttonMA->hovered(), true);
+ QCOMPARE(buttonHoveredSpy.count(), 1);
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(topSidebarHH->isHovered(), true);
+ QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(buttonMA->hovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 2);
+
+ QTest::mouseMove(window, outOfSidebar);
+ QCOMPARE(topSidebarHH->isHovered(), false);
+ QCOMPARE(sidebarHoveredSpy.count(), 2);
+ QCOMPARE(buttonMA->hovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 2);
+}
+
+void tst_HoverHandler::hoverHandlerAndUnderlyingMouseArea()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "lesHoverables.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem * bottomSidebar = window->rootObject()->findChild<QQuickItem *>("bottomSidebar");
+ QVERIFY(bottomSidebar);
+ QQuickMouseArea *bottomSidebarMA = bottomSidebar->findChild<QQuickMouseArea *>("bottomSidebarMA");
+ QVERIFY(bottomSidebarMA);
+ QQuickItem * button = bottomSidebar->findChild<QQuickItem *>("buttonWithHH");
+ QVERIFY(button);
+ QQuickHoverHandler *buttonHH = button->findChild<QQuickHoverHandler *>("buttonHH");
+ QVERIFY(buttonHH);
+
+ QPoint buttonCenter(button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint());
+ QPoint rightOfButton(button->mapToScene(QPointF(button->width() + 2, button->height() / 2)).toPoint());
+ QPoint outOfSidebar(bottomSidebar->mapToScene(QPointF(bottomSidebar->width() + 2, bottomSidebar->height() / 2)).toPoint());
+ QSignalSpy sidebarHoveredSpy(bottomSidebarMA, SIGNAL(hoveredChanged()));
+ QSignalSpy buttonHoveredSpy(buttonHH, SIGNAL(hoveredChanged()));
+
+ QTest::mouseMove(window, outOfSidebar);
+ QCOMPARE(bottomSidebarMA->hovered(), false);
+ QCOMPARE(sidebarHoveredSpy.count(), 0);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 0);
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(bottomSidebarMA->hovered(), true);
+ QCOMPARE(sidebarHoveredSpy.count(), 1);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 0);
+
+ QTest::mouseMove(window, buttonCenter);
+ QCOMPARE(bottomSidebarMA->hovered(), false);
+ QCOMPARE(sidebarHoveredSpy.count(), 2);
+ QCOMPARE(buttonHH->isHovered(), true);
+ QCOMPARE(buttonHoveredSpy.count(), 1);
+
+ QTest::mouseMove(window, rightOfButton);
+ QCOMPARE(bottomSidebarMA->hovered(), true);
+ QCOMPARE(sidebarHoveredSpy.count(), 3);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 2);
+
+ QTest::mouseMove(window, outOfSidebar);
+ QCOMPARE(bottomSidebarMA->hovered(), false);
+ QCOMPARE(sidebarHoveredSpy.count(), 4);
+ QCOMPARE(buttonHH->isHovered(), false);
+ QCOMPARE(buttonHoveredSpy.count(), 2);
+}
+
+void tst_HoverHandler::movingItemWithHoverHandler()
+{
+ if (isPlatformWayland())
+ QSKIP("Wayland: QCursor::setPos() doesn't work.");
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "lesHoverables.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem * paddle = window->rootObject()->findChild<QQuickItem *>("paddle");
+ QVERIFY(paddle);
+ QQuickHoverHandler *paddleHH = paddle->findChild<QQuickHoverHandler *>("paddleHH");
+ QVERIFY(paddleHH);
+
+ // Find the global coordinate of the paddle
+ const QPoint p(paddle->mapToScene(paddle->clipRect().center()).toPoint());
+ const QPoint paddlePos = window->mapToGlobal(p);
+
+ // Now hide the window, put the cursor where the paddle was and show it again
+ window->hide();
+ QTRY_COMPARE(window->isVisible(), false);
+ QCursor::setPos(paddlePos);
+ window->show();
+ QTest::qWaitForWindowExposed(window);
+
+ QTRY_COMPARE(paddleHH->isHovered(), true);
+
+ paddle->setX(100);
+ QTRY_COMPARE(paddleHH->isHovered(), false);
+
+ paddle->setX(p.x());
+ QTRY_COMPARE(paddleHH->isHovered(), true);
+
+ paddle->setX(540);
+ QTRY_COMPARE(paddleHH->isHovered(), false);
+}
+
+QTEST_MAIN(tst_HoverHandler)
+
+#include "tst_qquickhoverhandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml
new file mode 100644
index 0000000000..3cabde5f59
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchproperties.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ id: whiteRect
+ property real scale: -1.0
+ property int activeCount : 0
+ property int deactiveCount : 0
+ width: 320; height: 320
+ color: "white"
+ Rectangle {
+ id: blackRect
+ objectName: "blackrect"
+ color: "black"
+ y: 50
+ x: 50
+ width: 100
+ height: 100
+ opacity: (whiteRect.width-blackRect.x+whiteRect.height-blackRect.y-199)/200
+ Text { color: "white"; text: "opacity: " + blackRect.opacity + "\nscale: " + blackRect.scale}
+ Rectangle {
+ color: "red"
+ width: 6; height: 6; radius: 3
+ visible: pincharea.active
+ x: pincharea.centroid.position.x - radius
+ y: pincharea.centroid.position.y - radius
+ }
+
+ PinchHandler {
+ id: pincharea
+ objectName: "pinchHandler"
+ minimumScale: 1.0
+ maximumScale: 4.0
+ minimumRotation: 0.0
+ maximumRotation: 90.0
+ xAxis.maximum: 140
+ yAxis.maximum: 170
+ onActiveChanged: {
+ whiteRect.scale = pincharea.scale
+ if (active) ++activeCount
+ else ++deactiveCount;
+ }
+
+ onUpdated: {
+ whiteRect.scale = pincharea.scale
+ //whiteRect.pointCount = pincharea.pointCount
+ }
+ }
+ }
+ }
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml
new file mode 100644
index 0000000000..4d1a520c01
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/threeFingers.qml
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ property variant centroid : pinchHandler.centroid
+ property real scale: pinchHandler.scale
+ property int pointCount: 0
+ property bool pinchActive: pinchHandler.active
+ width: 240; height: 320
+
+ Rectangle {
+ id: blackRect
+ objectName: "blackrect"
+ color: "black"
+ y: 50
+ x: 50
+ width: 200
+ height: 200
+
+ PinchHandler {
+ id: pinchHandler
+ objectName: "pinchHandler"
+ minimumScale: 0.5
+ maximumScale: 2.0
+ minimumRotation: 0.0
+ maximumRotation: 0.0
+ minimumPointCount: 3
+ maximumPointCount: 3
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml
new file mode 100644
index 0000000000..46e9ccca87
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/data/transformedPinchHandler.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ width: 400
+ height: 400
+
+ Rectangle {
+ x: 100
+ y: 100
+ width: 200
+ height: 200
+ rotation: 45
+
+ Rectangle {
+ id: rect
+ scale: 0.5
+ color: "black"
+ anchors.fill: parent
+
+ PinchHandler {
+ objectName: "pinchHandler"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/qquickpinchhandler.pro b/tests/auto/quick/pointerhandlers/qquickpinchhandler/qquickpinchhandler.pro
new file mode 100644
index 0000000000..7e177d9786
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/qquickpinchhandler.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qquickpinchhandler
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qquickpinchhandler.cpp
+OTHER_FILES = \
+ data/pinchproperties.qml \
+ data/threeFingers.qml \
+ data/transformedPinchArea.qml
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+QT += core-private gui-private qml-private quick-private testlib
diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
new file mode 100644
index 0000000000..19fdae3b44
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp
@@ -0,0 +1,772 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <QtGui/QStyleHints>
+#include <qpa/qwindowsysteminterface.h>
+#include <private/qquickpinchhandler_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/qquickview.h>
+#include <QtQml/qqmlcontext.h>
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+class tst_QQuickPinchHandler: public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_QQuickPinchHandler() : device(0) { }
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void pinchProperties();
+ void scale();
+ void scaleThreeFingers();
+ void pan();
+ void dragAxesEnabled_data();
+ void dragAxesEnabled();
+ void retouch();
+ void cancel();
+ void transformedpinchHandler_data();
+ void transformedpinchHandler();
+
+private:
+ QQuickView *createView();
+ QTouchDevice *device;
+};
+void tst_QQuickPinchHandler::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ if (!device) {
+ device = new QTouchDevice;
+ device->setType(QTouchDevice::TouchScreen);
+ QWindowSystemInterface::registerTouchDevice(device);
+ }
+}
+
+void tst_QQuickPinchHandler::cleanupTestCase()
+{
+
+}
+
+static bool withinBounds(qreal lower, qreal num, qreal upper)
+{
+ return num >= lower && num <= upper;
+}
+
+void tst_QQuickPinchHandler::pinchProperties()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("pinchproperties.qml"));
+ window->show();
+ QVERIFY(window->rootObject() != nullptr);
+
+ QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+
+ // target
+ QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != nullptr);
+ QCOMPARE(blackRect, pinchHandler->target());
+ QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(rootItem != nullptr);
+ QSignalSpy targetSpy(pinchHandler, SIGNAL(targetChanged()));
+ pinchHandler->setTarget(rootItem);
+ QCOMPARE(targetSpy.count(),1);
+ pinchHandler->setTarget(rootItem);
+ QCOMPARE(targetSpy.count(),1);
+
+ // axis
+ /*
+ QCOMPARE(pinchHandler->axis(), QQuickPinch::XAndYAxis);
+ QSignalSpy axisSpy(pinchHandler, SIGNAL(dragAxisChanged()));
+ pinchHandler->setAxis(QQuickPinch::XAxis);
+ QCOMPARE(pinchHandler->axis(), QQuickPinch::XAxis);
+ QCOMPARE(axisSpy.count(),1);
+ pinchHandler->setAxis(QQuickPinch::XAxis);
+ QCOMPARE(axisSpy.count(),1);
+
+ // minimum and maximum drag properties
+ QSignalSpy xminSpy(pinchHandler, SIGNAL(minimumXChanged()));
+ QSignalSpy xmaxSpy(pinchHandler, SIGNAL(maximumXChanged()));
+ QSignalSpy yminSpy(pinchHandler, SIGNAL(minimumYChanged()));
+ QSignalSpy ymaxSpy(pinchHandler, SIGNAL(maximumYChanged()));
+
+ QCOMPARE(pinchHandler->xmin(), 0.0);
+ QCOMPARE(pinchHandler->xmax(), rootItem->width()-blackRect->width());
+ QCOMPARE(pinchHandler->ymin(), 0.0);
+ QCOMPARE(pinchHandler->ymax(), rootItem->height()-blackRect->height());
+
+ pinchHandler->setXmin(10);
+ pinchHandler->setXmax(10);
+ pinchHandler->setYmin(10);
+ pinchHandler->setYmax(10);
+
+ QCOMPARE(pinchHandler->xmin(), 10.0);
+ QCOMPARE(pinchHandler->xmax(), 10.0);
+ QCOMPARE(pinchHandler->ymin(), 10.0);
+ QCOMPARE(pinchHandler->ymax(), 10.0);
+
+ QCOMPARE(xminSpy.count(),1);
+ QCOMPARE(xmaxSpy.count(),1);
+ QCOMPARE(yminSpy.count(),1);
+ QCOMPARE(ymaxSpy.count(),1);
+
+ pinchHandler->setXmin(10);
+ pinchHandler->setXmax(10);
+ pinchHandler->setYmin(10);
+ pinchHandler->setYmax(10);
+
+ QCOMPARE(xminSpy.count(),1);
+ QCOMPARE(xmaxSpy.count(),1);
+ QCOMPARE(yminSpy.count(),1);
+ QCOMPARE(ymaxSpy.count(),1);
+ */
+
+ // minimum and maximum scale properties
+ QSignalSpy scaleMinSpy(pinchHandler, SIGNAL(minimumScaleChanged()));
+ QSignalSpy scaleMaxSpy(pinchHandler, SIGNAL(maximumScaleChanged()));
+
+ QCOMPARE(pinchHandler->minimumScale(), 1.0);
+ QCOMPARE(pinchHandler->maximumScale(), 4.0);
+
+ pinchHandler->setMinimumScale(0.5);
+ pinchHandler->setMaximumScale(1.5);
+
+ QCOMPARE(pinchHandler->minimumScale(), 0.5);
+ QCOMPARE(pinchHandler->maximumScale(), 1.5);
+
+ QCOMPARE(scaleMinSpy.count(),1);
+ QCOMPARE(scaleMaxSpy.count(),1);
+
+ pinchHandler->setMinimumScale(0.5);
+ pinchHandler->setMaximumScale(1.5);
+
+ QCOMPARE(scaleMinSpy.count(),1);
+ QCOMPARE(scaleMaxSpy.count(),1);
+
+ // minimum and maximum rotation properties
+ QSignalSpy rotMinSpy(pinchHandler, SIGNAL(minimumRotationChanged()));
+ QSignalSpy rotMaxSpy(pinchHandler, SIGNAL(maximumRotationChanged()));
+
+ QCOMPARE(pinchHandler->minimumRotation(), 0.0);
+ QCOMPARE(pinchHandler->maximumRotation(), 90.0);
+
+ pinchHandler->setMinimumRotation(-90.0);
+ pinchHandler->setMaximumRotation(45.0);
+
+ QCOMPARE(pinchHandler->minimumRotation(), -90.0);
+ QCOMPARE(pinchHandler->maximumRotation(), 45.0);
+
+ QCOMPARE(rotMinSpy.count(),1);
+ QCOMPARE(rotMaxSpy.count(),1);
+
+ pinchHandler->setMinimumRotation(-90.0);
+ pinchHandler->setMaximumRotation(45.0);
+
+ QCOMPARE(rotMinSpy.count(),1);
+ QCOMPARE(rotMaxSpy.count(),1);
+}
+
+QTouchEvent::TouchPoint makeTouchPoint(int id, QPoint p, QQuickView *v, QQuickItem *i)
+{
+ QTouchEvent::TouchPoint touchPoint(id);
+ touchPoint.setPos(i->mapFromScene(p));
+ touchPoint.setScreenPos(v->mapToGlobal(p));
+ touchPoint.setScenePos(p);
+ return touchPoint;
+}
+
+void tst_QQuickPinchHandler::scale()
+{
+ QQuickView *window = createView();
+ QScopedPointer<QQuickView> scope(window);
+ window->setSource(testFileUrl("pinchproperties.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(window->rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(root != nullptr);
+
+ // target
+ QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != nullptr);
+
+ QPoint p0(80, 80);
+ QPoint p1(100, 100);
+ {
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ pinchSequence.press(0, p0, window).commit();
+ QQuickTouchUtils::flush(window);
+ // In order for the stationary point to remember its previous position,
+ // we have to reuse the same pinchSequence object. Otherwise if we let it
+ // be destroyed and then start a new sequence, point 0 will default to being
+ // stationary at 0, 0, and pinchHandler will filter out that touchpoint because
+ // it is outside its bounds.
+ pinchSequence.stationary(0).press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+
+ QPoint pd(10, 10);
+ // move one point until PinchHandler activates
+ for (int pi = 0; pi < 10 && !pinchHandler->active(); ++pi) {
+ p1 += pd;
+ pinchSequence.stationary(0).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(pinchHandler->active(), true);
+ QLineF line(p0, p1);
+ const qreal startLength = line.length();
+
+ p1+=pd;
+ pinchSequence.stationary(0).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ line.setP2(p1);
+ qreal scale = line.length() / startLength;
+ QVERIFY(qFloatDistance(root->property("scale").toReal(), scale) < 10);
+ QVERIFY(qFloatDistance(blackRect->scale(), scale) < 10);
+
+ p1+=pd;
+ pinchSequence.stationary(0).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ line.setP2(p1);
+ scale = line.length() / startLength;
+
+ QVERIFY(qFloatDistance(root->property("scale").toReal(), scale) < 10);
+ QVERIFY(qFloatDistance(blackRect->scale(), scale) < 10);
+
+ QPointF expectedCentroid = p0 + (p1 - p0)/2;
+ QCOMPARE(pinchHandler->centroid().scenePosition(), expectedCentroid);
+ }
+
+ // scale beyond bound
+ p1 += QPoint(20, 20);
+ {
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ pinchSequence.stationary(0).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(blackRect->scale(), qreal(4)); // qquickpinchhandler does not manipulate scale property
+ pinchSequence.release(0, p0, window).release(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(pinchHandler->active(), false);
+}
+
+void tst_QQuickPinchHandler::scaleThreeFingers()
+{
+ QQuickView *window = createView();
+ QScopedPointer<QQuickView> scope(window);
+ window->setSource(testFileUrl("threeFingers.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(window->rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(root != nullptr);
+
+ // target
+ QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != nullptr);
+
+ // center of blackrect is at 150,150
+ QPoint p0(80, 80);
+ QPoint p1(220, 80);
+ QPoint p2(150, 220);
+ {
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ pinchSequence.press(0, p0, window).commit();
+ QQuickTouchUtils::flush(window);
+ // In order for the stationary point to remember its previous position,
+ // we have to reuse the same pinchSequence object. Otherwise if we let it
+ // be destroyed and then start a new sequence, point 0 will default to being
+ // stationary at 0, 0, and pinchHandler will filter out that touchpoint because
+ // it is outside its bounds.
+ pinchSequence.stationary(0).press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ pinchSequence.stationary(0).stationary(1).press(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ for (int i = 0; i < 5;++i) {
+ p0 += QPoint(-4, -4);
+ p1 += QPoint(+4, -4);
+ p2 += QPoint( 0, +6);
+ pinchSequence.move(0, p0,window).move(1, p1,window).move(2, p2,window).commit();
+ QQuickTouchUtils::flush(window);
+ }
+
+ QCOMPARE(pinchHandler->active(), true);
+ // scale we got was 1.1729088738267854364, but keep some slack
+ QVERIFY(withinBounds(1.163, root->property("scale").toReal(), 1.183));
+ // should not rotate
+ QCOMPARE(root->property("rotation").toReal(), 0.);
+
+ for (int i = 0; i < 5;++i) {
+ p0 += QPoint(-4, -4);
+ p1 += QPoint(+4, -4);
+ p2 += QPoint( 0, +6);
+ pinchSequence.move(0, p0,window).move(1, p1,window).move(2, p2,window).commit();
+ QQuickTouchUtils::flush(window);
+ }
+ // scale we got was 1.4613, but keep some slack
+ QVERIFY(withinBounds(1.361, root->property("scale").toReal(), 1.561));
+
+ // since points were moved symetrically around the y axis, centroid should remain at x:150
+ QCOMPARE(root->property("centroid").value<QQuickHandlerPoint>().scenePosition().x(), 150); // blackrect is at 50,50
+
+ // scale beyond bound, we should reach the maximumScale
+ p0 += QPoint(-40, -40);
+ p1 += QPoint(+40, -40);
+ p2 += QPoint( 0, +60);
+ pinchSequence.move(0, p0,window).move(1, p1,window).move(2, p2,window).commit();
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(root->property("scale").toReal(), 2.);
+ pinchSequence.release(0, p0, window).release(1, p1, window).release(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(pinchHandler->active(), false);
+}
+
+void tst_QQuickPinchHandler::pan()
+{
+ QQuickView *window = createView();
+ QScopedPointer<QQuickView> scope(window);
+ window->setSource(testFileUrl("pinchproperties.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(window->rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(root != nullptr);
+
+ // target
+ QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != nullptr);
+
+ QPoint p0(80, 80);
+ QPoint p1(100, 100);
+ {
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ pinchSequence.press(0, p0, window).commit();
+ QQuickTouchUtils::flush(window);
+ // In order for the stationary point to remember its previous position,
+ // we have to reuse the same pinchSequence object.
+ pinchSequence.stationary(0).press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!root->property("pinchActive").toBool());
+ QCOMPARE(root->property("scale").toReal(), -1.0);
+
+ p0 += QPoint(dragThreshold, 0);
+ p1 += QPoint(dragThreshold, 0);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ // movement < dragThreshold: pinchHandler not yet active
+ QVERIFY(!root->property("pinchActive").toBool());
+ QCOMPARE(root->property("scale").toReal(), -1.0);
+
+ // just above the dragThreshold: pinchHandler starts
+ p0 += QPoint(1, 0);
+ p1 += QPoint(1, 0);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(pinchHandler->active(), true);
+ QCOMPARE(root->property("scale").toReal(), 1.0);
+
+ // Calculation of the center point is tricky at first:
+ // center point of the two touch points in item coordinates:
+ // scene coordinates: (80, 80) + (dragThreshold, 0), (100, 100) + (dragThreshold, 0)
+ // = ((180+dT)/2, 180/2) = (90+dT, 90)
+ // item coordinates: (scene) - (50, 50) = (40+dT, 40)
+ QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 1, 90));
+ // pan started, but no actual movement registered yet:
+ // blackrect starts at 50,50
+ QCOMPARE(blackRect->x(), 50.0);
+ QCOMPARE(blackRect->y(), 50.0);
+
+ p0 += QPoint(10, 0);
+ p1 += QPoint(10, 0);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 11, 90));
+ QCOMPARE(blackRect->x(), 60.0);
+ QCOMPARE(blackRect->y(), 50.0);
+
+ p0 += QPoint(0, 10);
+ p1 += QPoint(0, 10);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 11, 90 + 10));
+ QCOMPARE(blackRect->x(), 60.0);
+ QCOMPARE(blackRect->y(), 60.0);
+
+ p0 += QPoint(10, 10);
+ p1 += QPoint(10, 10);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ // now the item moved again, thus the center point of the touch is moved in total by (10, 10)
+ QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 21, 90 + 20));
+ QCOMPARE(blackRect->x(), 70.0);
+ QCOMPARE(blackRect->y(), 70.0);
+ }
+
+ // pan x beyond bound
+ p0 += QPoint(100,100);
+ p1 += QPoint(100,100);
+ QTest::touchEvent(window, device).move(0, p0, window).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(blackRect->x(), 140.0);
+ QCOMPARE(blackRect->y(), 170.0);
+
+ QTest::touchEvent(window, device).release(0, p0, window).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!root->property("pinchActive").toBool());
+}
+
+void tst_QQuickPinchHandler::dragAxesEnabled_data()
+{
+ QTest::addColumn<bool>("xEnabled");
+ QTest::addColumn<bool>("yEnabled");
+
+ QTest::newRow("both enabled") << true << true;
+ QTest::newRow("x enabled") << true << false;
+ QTest::newRow("y enabled") << false << true;
+ QTest::newRow("both disabled") << false << false;
+}
+
+void tst_QQuickPinchHandler::dragAxesEnabled()
+{
+ QQuickView *window = createView();
+ QScopedPointer<QQuickView> scope(window);
+ window->setSource(testFileUrl("pinchproperties.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(window->rootObject() != nullptr);
+ QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != nullptr);
+ QQuickPinchHandler *pinchHandler = blackRect->findChild<QQuickPinchHandler*>();
+ QVERIFY(pinchHandler != nullptr);
+
+ QFETCH(bool, xEnabled);
+ QFETCH(bool, yEnabled);
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ pinchHandler->xAxis()->setEnabled(xEnabled);
+ pinchHandler->yAxis()->setEnabled(yEnabled);
+ QPoint c = blackRect->mapToScene(blackRect->clipRect().center()).toPoint();
+ QPoint p0 = c - QPoint(0, dragThreshold);
+ QPoint p1 = c + QPoint(0, dragThreshold);
+ QPoint blackRectPos = blackRect->position().toPoint();
+
+ // press two points, one above the rectangle's center and one below
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ pinchSequence.press(0, p0, window).press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+
+ // expand the pinch vertically
+ p0 -= QPoint(0, dragThreshold);
+ p1 += QPoint(0, dragThreshold);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ for (int pi = 0; pi < 4; ++pi) {
+ p0 -= QPoint(0, dragThreshold);
+ p1 += QPoint(0, dragThreshold);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ qCDebug(lcPointerTests) << pi << "active" << pinchHandler->active() << "pts" << p0 << p1
+ << "centroid" << pinchHandler->centroid().scenePosition()
+ << "rect pos" << blackRect->position() << "scale" << blackRect->scale();
+ }
+ QCOMPARE(pinchHandler->active(), true);
+ QVERIFY(blackRect->scale() >= 2.0);
+ // drag started, but we only did scaling without any translation
+ QCOMPARE(pinchHandler->centroid().scenePosition().toPoint(), c);
+ QCOMPARE(blackRect->position().toPoint().x(), blackRectPos.x());
+ QCOMPARE(blackRect->position().toPoint().y(), blackRectPos.y());
+
+ // drag diagonally
+ p0 += QPoint(150, 150);
+ p1 += QPoint(150, 150);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ // the target should move if the xAxis is enabled, or stay in place if not
+ qCDebug(lcPointerTests) << "after diagonal drag: pts" << p0 << p1
+ << "centroid" << pinchHandler->centroid().scenePosition()
+ << "rect pos" << blackRect->position() << "scale" << blackRect->scale();
+ QCOMPARE(pinchHandler->centroid().scenePosition().toPoint(), QPoint(250, 250));
+ QCOMPARE(blackRect->position().toPoint().x(), xEnabled ? 140 : blackRectPos.x()); // because of xAxis.maximum
+ QCOMPARE(blackRect->position().toPoint().y(), yEnabled ? 170 : blackRectPos.y()); // because of yAxis.maximum
+
+ QTest::touchEvent(window, device).release(0, p0, window).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+}
+
+// test pinchHandler, release one point, touch again to continue pinchHandler
+void tst_QQuickPinchHandler::retouch()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QQuickView *window = createView();
+ QScopedPointer<QQuickView> scope(window);
+ window->setSource(testFileUrl("pinchproperties.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(window->rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(root != nullptr);
+
+ // target
+ QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != nullptr);
+
+ QPoint p0(80, 80);
+ QPoint p1(100, 100);
+ {
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ pinchSequence.press(0, p0, window).commit();
+ QQuickTouchUtils::flush(window);
+ // In order for the stationary point to remember its previous position,
+ // we have to reuse the same pinchSequence object.
+ pinchSequence.stationary(0).press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ const QPoint delta(dragThreshold + 1, dragThreshold + 1);
+ p0 -= delta;
+ p1 += delta;
+ pinchSequence.move(0, p0,window).move(1, p1,window).commit();
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(root->property("scale").toReal(), 1.0);
+ QCOMPARE(pinchHandler->active(), true);
+
+ p0 -= delta;
+ p1 += delta;
+ pinchSequence.move(0, p0,window).move(1, p1,window).commit();
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(pinchHandler->active(), true);
+
+ // accept some slack
+ QVERIFY(withinBounds(1.4, root->property("scale").toReal(), 1.6));
+ QCOMPARE(pinchHandler->centroid().position(), QPointF(40, 40)); // blackrect is at 50,50
+ QVERIFY(withinBounds(1.4, blackRect->scale(), 1.6));
+
+ QCOMPARE(root->property("activeCount").toInt(), 1);
+ QCOMPARE(root->property("deactiveCount").toInt(), 0);
+
+ // Hold down the first finger but release the second one
+ pinchSequence.stationary(0).release(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(root->property("activeCount").toInt(), 1);
+ QCOMPARE(root->property("deactiveCount").toInt(), 1);
+
+ // Keep holding down the first finger and re-touch the second one, then move them both
+ pinchSequence.stationary(0).press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ p0 -= QPoint(10,10);
+ p1 += QPoint(10,10);
+ pinchSequence.move(0, p0, window).move(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+
+ // Lifting and retouching results in onPinchStarted being called again
+ QCOMPARE(root->property("activeCount").toInt(), 2);
+ QCOMPARE(root->property("deactiveCount").toInt(), 1);
+
+ pinchSequence.release(0, p0, window).release(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(pinchHandler->active(), false);
+ QCOMPARE(root->property("activeCount").toInt(), 2);
+ QCOMPARE(root->property("deactiveCount").toInt(), 2);
+ }
+}
+
+void tst_QQuickPinchHandler::cancel()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QQuickView *window = createView();
+ QScopedPointer<QQuickView> scope(window);
+ window->setSource(testFileUrl("pinchproperties.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(window->rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickPinchHandler *pinchHandler = window->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+
+ QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
+ QVERIFY(root != nullptr);
+
+ // target
+ QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != nullptr);
+
+ QPoint p0(80, 80);
+ QPoint p1(100, 100);
+ {
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ pinchSequence.press(0, p0, window).commit();
+ QQuickTouchUtils::flush(window);
+ // In order for the stationary point to remember its previous position,
+ // we have to reuse the same pinchSequence object. Otherwise if we let it
+ // be destroyed and then start a new sequence, point 0 will default to being
+ // stationary at 0, 0, and pinchHandler will filter out that touchpoint because
+ // it is outside its bounds.
+ pinchSequence.stationary(0).press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ const QPoint delta(dragThreshold + 1, dragThreshold + 1);
+ p0 -= delta;
+ p1 += delta;
+ pinchSequence.move(0, p0,window).move(1, p1,window).commit();
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(root->property("scale").toReal(), 1.0);
+ QCOMPARE(pinchHandler->active(), true);
+
+ p0 -= delta;
+ p1 += delta;
+ pinchSequence.move(0, p0,window).move(1, p1,window).commit();
+ QQuickTouchUtils::flush(window);
+
+ QVERIFY(withinBounds(1.4, root->property("scale").toReal(), 1.6));
+ QCOMPARE(pinchHandler->centroid().position(), QPointF(40, 40)); // blackrect is at 50,50
+ QVERIFY(withinBounds(1.4, blackRect->scale(), 1.6));
+
+ QSKIP("cancel is not supported atm");
+
+ QTouchEvent cancelEvent(QEvent::TouchCancel);
+ cancelEvent.setDevice(device);
+ QCoreApplication::sendEvent(window, &cancelEvent);
+ QQuickTouchUtils::flush(window);
+
+ QCOMPARE(root->property("scale").toReal(), 1.0);
+ QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
+ QCOMPARE(blackRect->scale(), 1.0);
+ QVERIFY(!root->property("pinchActive").toBool());
+ }
+}
+
+void tst_QQuickPinchHandler::transformedpinchHandler_data()
+{
+ QTest::addColumn<QPoint>("p0");
+ QTest::addColumn<QPoint>("p1");
+ QTest::addColumn<bool>("shouldPinch");
+
+ QTest::newRow("checking inner pinchHandler 1")
+ << QPoint(200, 140) << QPoint(200, 260) << true;
+
+ QTest::newRow("checking inner pinchHandler 2")
+ << QPoint(140, 200) << QPoint(200, 140) << true;
+
+ QTest::newRow("checking inner pinchHandler 3")
+ << QPoint(140, 200) << QPoint(260, 200) << true;
+
+ QTest::newRow("checking outer pinchHandler 1")
+ << QPoint(140, 140) << QPoint(260, 260) << false;
+
+ QTest::newRow("checking outer pinchHandler 2")
+ << QPoint(140, 140) << QPoint(200, 200) << false;
+
+ QTest::newRow("checking outer pinchHandler 3")
+ << QPoint(140, 260) << QPoint(260, 260) << false;
+}
+
+void tst_QQuickPinchHandler::transformedpinchHandler()
+{
+ QFETCH(QPoint, p0);
+ QFETCH(QPoint, p1);
+ QFETCH(bool, shouldPinch);
+
+ QQuickView *view = createView();
+ QScopedPointer<QQuickView> scope(view);
+ view->setSource(testFileUrl("transformedPinchHandler.qml"));
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view));
+ QVERIFY(view->rootObject() != nullptr);
+ qApp->processEvents();
+
+ QQuickPinchHandler *pinchHandler = view->rootObject()->findChild<QQuickPinchHandler*>("pinchHandler");
+ QVERIFY(pinchHandler != nullptr);
+
+ const int threshold = qApp->styleHints()->startDragDistance();
+
+ {
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, device);
+ // start pinchHandler
+ pinchSequence.press(0, p0, view).commit();
+ QQuickTouchUtils::flush(view);
+ // In order for the stationary point to remember its previous position,
+ // we have to reuse the same pinchSequence object.
+ pinchSequence.stationary(0).press(1, p1, view).commit();
+ QQuickTouchUtils::flush(view);
+
+ // we move along the line that the two points form.
+ // The distance we move should be above the threshold (threshold * 2 to be safe)
+ QVector2D delta(p1 - p0);
+ delta.normalize();
+ QVector2D movement = delta * (threshold * 2);
+ pinchSequence.stationary(0).move(1, p1 + movement.toPoint(), view).commit();
+ QQuickTouchUtils::flush(view);
+ QCOMPARE(pinchHandler->active(), shouldPinch);
+
+ // release pinchHandler
+ pinchSequence.release(0, p0, view).release(1, p1, view).commit();
+ QQuickTouchUtils::flush(view);
+ QCOMPARE(pinchHandler->active(), false);
+ }
+}
+
+QQuickView *tst_QQuickPinchHandler::createView()
+{
+ QQuickView *window = new QQuickView(0);
+ window->setGeometry(0,0,240,320);
+
+ return window;
+}
+
+QTEST_MAIN(tst_QQuickPinchHandler)
+
+#include "tst_qquickpinchhandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreated.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreated.qml
new file mode 100644
index 0000000000..8f774a7ec3
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreated.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.12
+import Qt.test 1.0
+
+Item {
+ id: root
+ objectName: "root Item"
+ width: 320
+ height: 480
+
+ Rectangle {
+ objectName: "eventItem's bounds"
+ anchors.fill: eventItem
+ color: "lightsteelblue"
+ }
+
+ EventItem {
+ id: eventItem
+ objectName: "eventItem1"
+ x: 5
+ y: 5
+ height: 30
+ width: 30
+
+ Component.onCompleted: handlerComponent.createObject(eventItem)
+
+ Component {
+ id: handlerComponent
+
+ EventHandler {
+ objectName: "eventHandler"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreatedInWindow.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreatedInWindow.qml
new file mode 100644
index 0000000000..058726b267
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreatedInWindow.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.12
+import QtQuick.Window 2.12
+import Qt.test 1.0
+
+Window {
+ id: root
+ objectName: "root Window"
+ width: 320
+ height: 480
+
+ Component.onCompleted: handlerComponent.createObject(root)
+
+ Component {
+ id: handlerComponent
+
+ EventHandler {
+ objectName: "eventHandler"
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/handlerInWindow.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/handlerInWindow.qml
new file mode 100644
index 0000000000..49ec9be4a7
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/handlerInWindow.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.12
+import QtQuick.Window 2.12
+import Qt.test 1.0
+
+Window {
+ id: root
+ objectName: "root Window"
+ width: 320
+ height: 480
+
+ EventHandler {
+ objectName: "eventHandler"
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/singleitem.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/singleitem.qml
new file mode 100644
index 0000000000..126cf3ff2b
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/singleitem.qml
@@ -0,0 +1,28 @@
+import QtQuick 2.8
+import Qt.test 1.0
+
+Item {
+ id: root
+ objectName: "root Item"
+ width: 320
+ height: 480
+
+ Rectangle {
+ objectName: "eventItem's bounds"
+ anchors.fill: eventItem
+ color: "lightsteelblue"
+ }
+
+ EventItem {
+ id: eventItem
+ objectName: "eventItem1"
+ x: 5
+ y: 5
+ height: 30
+ width: 30
+
+ EventHandler {
+ objectName: "eventHandler"
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/qquickpointerhandler.pro b/tests/auto/quick/pointerhandlers/qquickpointerhandler/qquickpointerhandler.pro
new file mode 100644
index 0000000000..c386969206
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/qquickpointerhandler.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+
+TARGET = tst_qquickpointerhandler
+QT += core-private gui-private qml-private quick-private testlib
+
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qquickpointerhandler.cpp
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+# OTHER_FILES += data/foo.qml
+
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
new file mode 100644
index 0000000000..2b6482465c
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
@@ -0,0 +1,685 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <private/qdebug_p.h>
+#include <QtGui/qstylehints.h>
+#include <QtQuick/private/qquickpointerhandler_p.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
+
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+class Event
+{
+ Q_GADGET
+public:
+ enum Destination {
+ FilterDestination,
+ MouseDestination,
+ TouchDestination,
+ HandlerDestination
+ };
+ Q_ENUM(Destination)
+
+ Event(Destination d, QEvent::Type t, Qt::TouchPointState s, int grabTransition, QPointF item, QPointF scene)
+ : destination(d), type(t), state(s), grabTransition(grabTransition), posWrtItem(item), posWrtScene(scene)
+ {}
+
+ Destination destination;
+ QEvent::Type type; // if this represents a QEvent that was received
+ Qt::TouchPointState state; // if this represents an event (pointer, touch or mouse)
+ int grabTransition; // if this represents an onGrabChanged() notification (QQuickEventPoint::GrabTransition)
+ QPointF posWrtItem;
+ QPointF posWrtScene;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const class Event &event) {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ dbg << "Event(";
+ QtDebugUtils::formatQEnum(dbg, event.destination);
+ dbg << ' ';
+ QtDebugUtils::formatQEnum(dbg, event.type);
+ dbg << ' ';
+ QtDebugUtils::formatQEnum(dbg, event.state);
+ if (event.grabTransition) {
+ dbg << ' ';
+ QtDebugUtils::formatQEnum(dbg, QQuickEventPoint::GrabTransition(event.grabTransition));
+ }
+ dbg << " @ ";
+ QtDebugUtils::formatQPoint(dbg, event.posWrtItem);
+ dbg << " S ";
+ QtDebugUtils::formatQPoint(dbg, event.posWrtScene);
+ dbg << ')';
+ return dbg;
+}
+#endif
+
+enum {
+ NoGrab = 0,
+};
+
+class EventItem : public QQuickItem
+{
+ Q_OBJECT
+public:
+ EventItem(QQuickItem *parent = nullptr)
+ : QQuickItem(parent), acceptPointer(false), grabPointer(false), acceptMouse(false), acceptTouch(false), filterTouch(false)
+ {}
+
+ inline int grabTransition(bool accept, Qt::TouchPointState state) {
+ return (accept && (state != Qt::TouchPointReleased)) ? (int)QQuickEventPoint::GrabExclusive : (int)NoGrab;
+ }
+
+ void touchEvent(QTouchEvent *event)
+ {
+ qCDebug(lcPointerTests) << event << "will accept?" << acceptTouch;
+ for (const QTouchEvent::TouchPoint &tp : event->touchPoints())
+ eventList.append(Event(Event::TouchDestination, event->type(), tp.state(), grabTransition(acceptTouch, tp.state()), tp.pos(), tp.scenePos()));
+ event->setAccepted(acceptTouch);
+ }
+ void mousePressEvent(QMouseEvent *event)
+ {
+ qCDebug(lcPointerTests) << event;
+ eventList.append(Event(Event::MouseDestination, event->type(), Qt::TouchPointPressed, grabTransition(acceptMouse, Qt::TouchPointPressed), event->pos(), event->windowPos()));
+ event->setAccepted(acceptMouse);
+ }
+ void mouseMoveEvent(QMouseEvent *event)
+ {
+ qCDebug(lcPointerTests) << event;
+ eventList.append(Event(Event::MouseDestination, event->type(), Qt::TouchPointMoved, grabTransition(acceptMouse, Qt::TouchPointMoved), event->pos(), event->windowPos()));
+ event->setAccepted(acceptMouse);
+ }
+ void mouseReleaseEvent(QMouseEvent *event)
+ {
+ qCDebug(lcPointerTests) << event;
+ eventList.append(Event(Event::MouseDestination, event->type(), Qt::TouchPointReleased, grabTransition(acceptMouse, Qt::TouchPointReleased), event->pos(), event->windowPos()));
+ event->setAccepted(acceptMouse);
+ }
+ void mouseDoubleClickEvent(QMouseEvent *event)
+ {
+ qCDebug(lcPointerTests) << event;
+ eventList.append(Event(Event::MouseDestination, event->type(), Qt::TouchPointPressed, grabTransition(acceptMouse, Qt::TouchPointPressed), event->pos(), event->windowPos()));
+ event->setAccepted(acceptMouse);
+ }
+
+ void mouseUngrabEvent()
+ {
+ qCDebug(lcPointerTests);
+ eventList.append(Event(Event::MouseDestination, QEvent::UngrabMouse, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive, QPoint(0,0), QPoint(0,0)));
+ }
+
+ bool event(QEvent *event)
+ {
+ qCDebug(lcPointerTests) << event;
+ return QQuickItem::event(event);
+ }
+
+ QList<Event> eventList;
+ bool acceptPointer;
+ bool grabPointer;
+ bool acceptMouse;
+ bool acceptTouch;
+ bool filterTouch; // when used as event filter
+
+ bool eventFilter(QObject *o, QEvent *event)
+ {
+ qCDebug(lcPointerTests) << event << o;
+ if (event->type() == QEvent::TouchBegin ||
+ event->type() == QEvent::TouchUpdate ||
+ event->type() == QEvent::TouchCancel ||
+ event->type() == QEvent::TouchEnd) {
+ QTouchEvent *touch = static_cast<QTouchEvent*>(event);
+ for (const QTouchEvent::TouchPoint &tp : touch->touchPoints())
+ eventList.append(Event(Event::FilterDestination, event->type(), tp.state(), QQuickEventPoint::GrabExclusive, tp.pos(), tp.scenePos()));
+ if (filterTouch)
+ event->accept();
+ return true;
+ }
+ return false;
+ }
+};
+
+#define QCOMPARE_EVENT(i, d, t, s, g) \
+ {\
+ const Event &event = eventItem1->eventList.at(i);\
+ QCOMPARE(event.destination, d);\
+ QCOMPARE(event.type, t);\
+ QCOMPARE(event.state, s);\
+ QCOMPARE(event.grabTransition, g);\
+ }\
+
+class EventHandler : public QQuickPointerHandler
+{
+public:
+ void handlePointerEventImpl(QQuickPointerEvent *event) override
+ {
+ QQuickPointerHandler::handlePointerEventImpl(event);
+ if (!enabled())
+ return;
+ if (event->isPressEvent())
+ ++pressEventCount;
+ if (event->isReleaseEvent())
+ ++releaseEventCount;
+ EventItem *item = qmlobject_cast<EventItem *>(target());
+ if (!item) {
+ event->point(0)->setGrabberPointerHandler(this);
+ return;
+ }
+ qCDebug(lcPointerTests) << item->objectName() << event;
+ int c = event->pointCount();
+ for (int i = 0; i < c; ++i) {
+ QQuickEventPoint *point = event->point(i);
+ if (item->acceptPointer)
+ point->setAccepted(item->acceptPointer); // does NOT imply a grab
+ if (item->grabPointer)
+ setExclusiveGrab(point, true);
+ qCDebug(lcPointerTests) << " " << i << ":" << point << "accepted?" << item->acceptPointer << "grabbed?" << (point->exclusiveGrabber() == this);
+ item->eventList.append(Event(Event::HandlerDestination, QEvent::Pointer,
+ static_cast<Qt::TouchPointState>(point->state()),
+ item->grabPointer ? (int)QQuickEventPoint::GrabExclusive : (int)NoGrab,
+ eventPos(point), point->scenePosition()));
+ }
+ }
+
+ void onGrabChanged(QQuickPointerHandler *, QQuickEventPoint::GrabTransition stateChange, QQuickEventPoint *point) override
+ {
+ EventItem *item = qmlobject_cast<EventItem *>(target());
+ if (item)
+ item->eventList.append(Event(Event::HandlerDestination, QEvent::None,
+ static_cast<Qt::TouchPointState>(point->state()), stateChange, eventPos(point), point->scenePosition()));
+ }
+
+ int pressEventCount = 0;
+ int releaseEventCount = 0;
+};
+
+class tst_PointerHandlers : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_PointerHandlers()
+ :touchDevice(QTest::createTouchDevice())
+ {}
+
+private slots:
+ void initTestCase();
+
+ void touchEventDelivery_data();
+ void touchEventDelivery();
+ void mouseEventDelivery();
+ void touchReleaseOutside_data();
+ void touchReleaseOutside();
+ void dynamicCreation();
+ void handlerInWindow();
+ void dynamicCreationInWindow();
+
+protected:
+ bool eventFilter(QObject *, QEvent *event)
+ {
+ Qt::TouchPointState tpState;
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ tpState = Qt::TouchPointPressed;
+ break;
+ case QEvent::MouseMove:
+ tpState = Qt::TouchPointMoved;
+ break;
+ case QEvent::MouseButtonRelease:
+ tpState = Qt::TouchPointReleased;
+ break;
+ default:
+ // So far we aren't recording filtered touch events here - they would be quite numerous in some cases
+ return false;
+ }
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ filteredEventList.append(Event(Event::FilterDestination, event->type(), tpState,
+ 0, me->pos(), me->globalPos()));
+ return false;
+ }
+
+private:
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+ QTouchDevice *touchDevice;
+ QList<Event> filteredEventList;
+};
+
+void tst_PointerHandlers::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+{
+ window.reset(new QQuickView);
+// window->setGeometry(0,0,240,320);
+ window->setSource(testFileUrl(fileName));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+}
+
+void tst_PointerHandlers::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem");
+ qmlRegisterType<EventHandler>("Qt.test", 1, 0, "EventHandler");
+}
+
+void tst_PointerHandlers::touchEventDelivery_data()
+{
+ QTest::addColumn<bool>("synthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents
+ QTest::newRow("no synth") << false;
+ QTest::newRow("synth") << true;
+}
+
+void tst_PointerHandlers::touchEventDelivery()
+{
+ QFETCH(bool, synthMouse);
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, synthMouse);
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "singleitem.qml");
+ QQuickView * window = windowPtr.data();
+
+ EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
+ QVERIFY(eventItem1);
+
+ // Do not accept anything
+ QPoint p1 = QPoint(20, 20);
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_COMPARE(eventItem1->eventList.size(), synthMouse ? 3 : 2);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab);
+ QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, Qt::TouchPointPressed, NoGrab);
+ if (synthMouse)
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, NoGrab);
+ p1 += QPoint(10, 0);
+ QTest::touchEvent(window, touchDevice).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 4 : 3);
+ QCOMPARE_EVENT(eventItem1->eventList.size() - 1, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, NoGrab);
+ QTest::touchEvent(window, touchDevice).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 5 : 4);
+ QCOMPARE_EVENT(eventItem1->eventList.size() - 1, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab);
+ eventItem1->eventList.clear();
+
+ // Accept touch
+ eventItem1->acceptTouch = true;
+ p1 = QPoint(20, 20);
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab);
+ QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive);
+ auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), eventItem1);
+ p1 += QPoint(10, 0);
+ QTest::touchEvent(window, touchDevice).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 4);
+ QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, NoGrab);
+ QCOMPARE_EVENT(3, Event::TouchDestination, QEvent::TouchUpdate, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive);
+ QTest::touchEvent(window, touchDevice).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 6);
+ QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab);
+ QCOMPARE_EVENT(5, Event::TouchDestination, QEvent::TouchEnd, Qt::TouchPointReleased, NoGrab);
+ eventItem1->eventList.clear();
+
+ // wait to avoid getting a double click event
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
+
+ // Accept mouse
+ eventItem1->acceptTouch = false;
+ eventItem1->acceptMouse = true;
+ eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
+ p1 = QPoint(20, 20);
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 3 : 2);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab);
+ QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, Qt::TouchPointPressed, NoGrab);
+ if (synthMouse)
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE(window->mouseGrabberItem(), synthMouse ? eventItem1 : nullptr);
+
+ QPointF localPos = eventItem1->mapFromScene(p1);
+ QPointF scenePos = p1; // item is at 0,0
+ QCOMPARE(eventItem1->eventList.at(1).posWrtItem, localPos);
+ QCOMPARE(eventItem1->eventList.at(1).posWrtScene, scenePos);
+ if (synthMouse) {
+ QCOMPARE(eventItem1->eventList.at(2).posWrtItem, localPos);
+ QCOMPARE(eventItem1->eventList.at(2).posWrtScene, scenePos);
+ }
+
+ p1 += QPoint(10, 0);
+ QTest::touchEvent(window, touchDevice).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 6 : 3);
+ if (synthMouse) {
+ QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, NoGrab);
+ QCOMPARE_EVENT(4, Event::TouchDestination, QEvent::TouchUpdate, Qt::TouchPointMoved, NoGrab);
+ QCOMPARE_EVENT(5, Event::MouseDestination, QEvent::MouseMove, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive);
+ }
+ QTest::touchEvent(window, touchDevice).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 10 : 4);
+ if (synthMouse) {
+ QCOMPARE_EVENT(6, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab);
+ QCOMPARE_EVENT(7, Event::TouchDestination, QEvent::TouchEnd, Qt::TouchPointReleased, NoGrab);
+ QCOMPARE_EVENT(8, Event::MouseDestination, QEvent::MouseButtonRelease, Qt::TouchPointReleased, NoGrab);
+ QCOMPARE_EVENT(9, Event::MouseDestination, QEvent::UngrabMouse, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive);
+ } else {
+ QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab);
+ }
+ eventItem1->eventList.clear();
+
+ // wait to avoid getting a double click event
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
+
+ // Accept mouse buttons but not the touch event
+ eventItem1->acceptTouch = false;
+ eventItem1->acceptMouse = false;
+ eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
+ p1 = QPoint(20, 20);
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 3 : 2);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab);
+ QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, Qt::TouchPointPressed, NoGrab);
+ if (synthMouse)
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, NoGrab);
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), nullptr);
+ p1 += QPoint(10, 0);
+ QTest::touchEvent(window, touchDevice).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 4 : 3);
+ QTest::touchEvent(window, touchDevice).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 5 : 4);
+ eventItem1->eventList.clear();
+
+ // wait to avoid getting a double click event
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
+
+ // Accept touch
+ eventItem1->acceptTouch = true;
+ eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
+ p1 = QPoint(20, 20);
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab);
+ QCOMPARE_EVENT(1, Event::TouchDestination, QEvent::TouchBegin, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive);
+ p1 += QPoint(10, 0);
+ QTest::touchEvent(window, touchDevice).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 4);
+ QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, NoGrab);
+ QCOMPARE_EVENT(3, Event::TouchDestination, QEvent::TouchUpdate, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive);
+ QTest::touchEvent(window, touchDevice).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 6);
+ QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, NoGrab);
+ QCOMPARE_EVENT(5, Event::TouchDestination, QEvent::TouchEnd, Qt::TouchPointReleased, NoGrab);
+ eventItem1->eventList.clear();
+
+ // Accept pointer events
+ eventItem1->acceptPointer = true;
+ eventItem1->grabPointer = true;
+ p1 = QPoint(20, 20);
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::None, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive);
+ p1 += QPoint(10, 0);
+ QTest::touchEvent(window, touchDevice).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive);
+ QTest::touchEvent(window, touchDevice).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(eventItem1->eventList.size(), 5);
+ qCDebug(lcPointerTests) << eventItem1->eventList;
+ QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::None, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive);
+ eventItem1->eventList.clear();
+}
+
+void tst_PointerHandlers::mouseEventDelivery()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "singleitem.qml");
+ QQuickView * window = windowPtr.data();
+
+ EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
+ QVERIFY(eventItem1);
+
+ // Do not accept anything
+ QPoint p1 = QPoint(20, 20);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(eventItem1->eventList.size(), 2);
+ p1 += QPoint(10, 0);
+ QTest::mouseMove(window, p1);
+ QCOMPARE(eventItem1->eventList.size(), 3);
+ QTest::mouseRelease(window, Qt::LeftButton);
+ QCOMPARE(eventItem1->eventList.size(), 3);
+ eventItem1->eventList.clear();
+
+ // wait to avoid getting a double click event
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
+
+ // Accept mouse
+ eventItem1->acceptTouch = false;
+ eventItem1->acceptMouse = true;
+ eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
+ p1 = QPoint(20, 20);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab);
+ QCOMPARE_EVENT(1, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE(window->mouseGrabberItem(), eventItem1);
+
+ QPointF localPos = eventItem1->mapFromScene(p1);
+ QPointF scenePos = p1; // item is at 0,0
+ QCOMPARE(eventItem1->eventList.at(0).posWrtItem, localPos);
+ QCOMPARE(eventItem1->eventList.at(0).posWrtScene, scenePos);
+ QCOMPARE(eventItem1->eventList.at(1).posWrtItem, localPos);
+ QCOMPARE(eventItem1->eventList.at(1).posWrtScene, scenePos);
+
+ p1 += QPoint(10, 0);
+ QTest::mouseMove(window, p1);
+ QCOMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseMove, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(eventItem1->eventList.size(), 5);
+ QCOMPARE_EVENT(3, Event::MouseDestination, QEvent::MouseButtonRelease, Qt::TouchPointReleased, NoGrab);
+ QCOMPARE_EVENT(4, Event::MouseDestination, QEvent::UngrabMouse, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive);
+ eventItem1->eventList.clear();
+
+ // wait to avoid getting a double click event
+ QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
+
+ // Grab pointer events
+ eventItem1->acceptMouse = false;
+ eventItem1->acceptPointer = true;
+ eventItem1->grabPointer = true;
+ p1 = QPoint(20, 20);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::None, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, 0);
+ p1 += QPoint(10, 0);
+ QTest::mouseMove(window, p1);
+ QCOMPARE(eventItem1->eventList.size(), 4);
+ QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(eventItem1->eventList.size(), 6);
+ QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, QQuickEventPoint::GrabExclusive);
+ QCOMPARE_EVENT(5, Event::HandlerDestination, QEvent::None, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive);
+ eventItem1->eventList.clear();
+}
+
+void tst_PointerHandlers::touchReleaseOutside_data()
+{
+ QTest::addColumn<bool>("acceptPointer");
+ QTest::addColumn<bool>("grabPointer");
+ QTest::addColumn<int>("eventCount");
+ QTest::addColumn<int>("endIndexToTest");
+ QTest::addColumn<int>("endDestination"); // Event::Destination
+ QTest::addColumn<int>("endType"); // QEvent::Type
+ QTest::addColumn<int>("endState"); // Qt::TouchPointState
+ QTest::addColumn<int>("endGrabState"); // Qt::TouchPointState
+
+ QTest::newRow("reject and ignore") << false << false << 6 << 5 << (int)Event::TouchDestination
+ << (int)QEvent::TouchEnd << (int)Qt::TouchPointReleased << (int)NoGrab;
+ QTest::newRow("reject and grab") << false << true << 5 << 4 << (int)Event::HandlerDestination
+ << (int)QEvent::None << (int)Qt::TouchPointReleased << (int)QQuickEventPoint::UngrabExclusive;
+ QTest::newRow("accept and ignore") << true << false << 1 << 0 << (int)Event::HandlerDestination
+ << (int)QEvent::Pointer << (int)Qt::TouchPointPressed << (int)NoGrab;
+ QTest::newRow("accept and grab") << true << true << 5 << 4 << (int)Event::HandlerDestination
+ << (int)QEvent::None << (int)Qt::TouchPointReleased << (int)QQuickEventPoint::UngrabExclusive;
+}
+
+void tst_PointerHandlers::touchReleaseOutside()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "singleitem.qml");
+ QQuickView * window = windowPtr.data();
+
+ QFETCH(bool, acceptPointer);
+ QFETCH(bool, grabPointer);
+ QFETCH(int, eventCount);
+ QFETCH(int, endIndexToTest);
+ QFETCH(int, endDestination);
+ QFETCH(int, endType);
+ QFETCH(int, endState);
+ QFETCH(int, endGrabState);
+
+ EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
+ QVERIFY(eventItem1);
+
+ eventItem1->acceptTouch = true;
+ eventItem1->acceptPointer = acceptPointer;
+ eventItem1->grabPointer = grabPointer;
+
+ QPoint p1 = QPoint(20, 20);
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1.setX(eventItem1->mapToScene(eventItem1->clipRect().bottomRight()).x() + 10);
+ QTest::touchEvent(window, touchDevice).move(0, p1, window);
+ QTest::touchEvent(window, touchDevice).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ qCDebug(lcPointerTests) << eventItem1->eventList;
+ QCOMPARE(eventItem1->eventList.size(), eventCount);
+ QCOMPARE_EVENT(endIndexToTest, endDestination, endType, endState, endGrabState);
+}
+
+void tst_PointerHandlers::dynamicCreation()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "dynamicallyCreated.qml");
+ QQuickView * window = windowPtr.data();
+
+ EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
+ QVERIFY(eventItem1);
+ EventHandler *handler = window->rootObject()->findChild<EventHandler*>("eventHandler");
+ QVERIFY(handler);
+
+ QCOMPARE(handler->parentItem(), eventItem1);
+ QCOMPARE(handler->target(), eventItem1);
+
+ QPoint p1(20, 20);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab);
+ QCOMPARE_EVENT(1, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, NoGrab);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+}
+
+void tst_PointerHandlers::handlerInWindow()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("handlerInWindow.qml"));
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(component.create());
+ QScopedPointer<QQuickWindow> cleanup(window);
+ QVERIFY(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ EventHandler *handler = window->contentItem()->findChild<EventHandler*>("eventHandler");
+ QVERIFY(handler);
+
+ QCOMPARE(handler->parentItem(), window->contentItem());
+ QCOMPARE(handler->target(), window->contentItem());
+
+ QPoint p1(20, 20);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(handler->pressEventCount, 1);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(handler->releaseEventCount, 1);
+}
+
+void tst_PointerHandlers::dynamicCreationInWindow()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("dynamicallyCreatedInWindow.qml"));
+ QQuickWindow *window = qobject_cast<QQuickWindow*>(component.create());
+ QScopedPointer<QQuickWindow> cleanup(window);
+ QVERIFY(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ EventHandler *handler = window->contentItem()->findChild<EventHandler*>("eventHandler");
+ QVERIFY(handler);
+
+ QCOMPARE(handler->parentItem(), window->contentItem());
+ QCOMPARE(handler->target(), window->contentItem());
+
+ QPoint p1(20, 20);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(handler->pressEventCount, 1);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(handler->releaseEventCount, 1);
+}
+
+QTEST_MAIN(tst_PointerHandlers)
+
+#include "tst_qquickpointerhandler.moc"
+
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml
new file mode 100644
index 0000000000..3f50d7c761
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/multiPointTracker.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ width: 400; height: 400
+
+ PointHandler {
+ id: ph1
+ objectName: "ph1"
+
+ target: Rectangle {
+ parent: root
+ visible: ph1.active
+ x: ph1.point.position.x - width / 2
+ y: ph1.point.position.y - height / 2
+ width: 140
+ height: width
+ radius: width / 2
+ color: "orange"
+ opacity: 0.3
+ }
+ }
+
+ PointHandler {
+ id: ph2
+ objectName: "ph2"
+
+ target: Rectangle {
+ parent: root
+ visible: ph2.active
+ x: ph2.point.position.x - width / 2
+ y: ph2.point.position.y - height / 2
+ width: 140
+ height: width
+ radius: width / 2
+ color: "orange"
+ opacity: 0.3
+ }
+ }
+
+ PointHandler {
+ id: ph3
+ objectName: "ph3"
+
+ target: Rectangle {
+ parent: root
+ visible: ph3.active
+ x: ph3.point.position.x - width / 2
+ y: ph3.point.position.y - height / 2
+ width: 140
+ height: width
+ radius: width / 2
+ color: "orange"
+ opacity: 0.3
+ }
+ }
+}
+
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml
new file mode 100644
index 0000000000..674bbda850
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/data/pointTracker.qml
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ width: 200
+ height: 200
+ Rectangle {
+ id: rect
+ objectName: "pointTracker"
+ width: 20
+ height: 20
+ radius: 10
+ color: "green"
+ x: handler.point.position.x
+ y: handler.point.position.y
+ }
+
+ Text {
+ id: text
+ anchors.top: rect.bottom
+ anchors.left: rect.right
+ text: "<" + handler.point.position.x + ", " + handler.point.position.y + "> " + handler.point.pressedButtons + " [" + handler.point.pressure + "]"
+ }
+
+ PointHandler {
+ id: handler
+ objectName: "pointHandler"
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/qquickpointhandler.pro b/tests/auto/quick/pointerhandlers/qquickpointhandler/qquickpointhandler.pro
new file mode 100644
index 0000000000..d64fc96d74
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/qquickpointhandler.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+
+TARGET = tst_qquickpointhandler
+QT += core-private gui-private qml-private quick-private testlib
+
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qquickpointhandler.cpp
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/pointTracker.qml \
diff --git a/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
new file mode 100644
index 0000000000..d0b3bc3d36
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickpointhandler/tst_qquickpointhandler.cpp
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtQuick/qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickpointhandler_p.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <private/qquickwindow_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlproperty.h>
+
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+class tst_PointHandler : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_PointHandler()
+ : touchDevice(QTest::createTouchDevice())
+ {}
+
+private slots:
+ void initTestCase();
+
+ void singleTouch();
+ void simultaneousMultiTouch();
+ void pressedMultipleButtons_data();
+ void pressedMultipleButtons();
+
+private:
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+ QTouchDevice *touchDevice;
+};
+
+void tst_PointHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+{
+ window.reset(new QQuickView);
+ window->setSource(testFileUrl(fileName));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+}
+
+void tst_PointHandler::initTestCase()
+{
+ // This test assumes that we don't get synthesized mouse events from QGuiApplication
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
+
+ QQmlDataTest::initTestCase();
+}
+
+void tst_PointHandler::singleTouch()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "pointTracker.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem *tracker = window->rootObject()->findChild<QQuickItem *>("pointTracker");
+ QVERIFY(tracker);
+ QQuickPointHandler *handler = window->rootObject()->findChild<QQuickPointHandler *>("pointHandler");
+ QVERIFY(handler);
+
+ QSignalSpy activeSpy(handler, SIGNAL(activeChanged()));
+ QSignalSpy pointSpy(handler, SIGNAL(pointChanged()));
+ QSignalSpy translationSpy(handler, SIGNAL(translationChanged()));
+
+ QPoint point(100,100);
+ QTest::touchEvent(window, touchDevice).press(1, point, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_COMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.count(), 1);
+ QCOMPARE(pointSpy.count(), 1);
+ QCOMPARE(handler->point().position().toPoint(), point);
+ QCOMPARE(handler->point().scenePosition().toPoint(), point);
+ QCOMPARE(handler->point().pressedButtons(), Qt::NoButton);
+ QCOMPARE(handler->translation(), QVector2D());
+ QCOMPARE(translationSpy.count(), 1);
+
+ point += QPoint(10, 10);
+ QTest::touchEvent(window, touchDevice).move(1, point, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(activeSpy.count(), 1);
+ QCOMPARE(pointSpy.count(), 2);
+ QCOMPARE(handler->point().position().toPoint(), point);
+ QCOMPARE(handler->point().scenePosition().toPoint(), point);
+ QCOMPARE(handler->point().pressPosition().toPoint(), QPoint(100, 100));
+ QCOMPARE(handler->point().scenePressPosition().toPoint(), QPoint(100, 100));
+ QCOMPARE(handler->point().pressedButtons(), Qt::NoButton);
+ QVERIFY(handler->point().velocity().x() > 0);
+ QVERIFY(handler->point().velocity().y() > 0);
+ QCOMPARE(handler->translation(), QVector2D(10, 10));
+ QCOMPARE(translationSpy.count(), 2);
+
+ QTest::touchEvent(window, touchDevice).release(1, point, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_COMPARE(handler->active(), false);
+ QCOMPARE(activeSpy.count(), 2);
+ QCOMPARE(pointSpy.count(), 3);
+ QCOMPARE(handler->translation(), QVector2D());
+ QCOMPARE(translationSpy.count(), 3);
+}
+
+void tst_PointHandler::simultaneousMultiTouch()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "multiPointTracker.qml");
+ QQuickView * window = windowPtr.data();
+ QList<QQuickPointHandler *> handlers = window->rootObject()->findChildren<QQuickPointHandler *>();
+ QCOMPARE(handlers.count(), 3);
+
+ QVector<QSignalSpy*> activeSpies;
+ QVector<QSignalSpy*> pointSpies;
+ QVector<QSignalSpy*> translationSpies;
+ QVector<QPoint> points{{100,100}, {200, 200}, {100, 300}};
+ QVector<QPoint> pressPoints = points;
+ for (auto h : handlers) {
+ activeSpies << new QSignalSpy(h, SIGNAL(activeChanged()));
+ pointSpies << new QSignalSpy(h, SIGNAL(pointChanged()));
+ translationSpies << new QSignalSpy(h, SIGNAL(translationChanged()));
+ }
+
+ QTest::touchEvent(window, touchDevice).press(1, points[0], window).press(2, points[1], window).press(3, points[2], window);
+ QQuickTouchUtils::flush(window);
+ QVector<int> pointIndexPerHandler;
+ int i = 0;
+ for (auto h : handlers) {
+ QTRY_COMPARE(h->active(), true);
+ QCOMPARE(activeSpies[i]->count(), 1);
+ QCOMPARE(pointSpies[i]->count(), 1);
+ int chosenPointIndex = points.indexOf(h->point().position().toPoint());
+ QVERIFY(chosenPointIndex != -1);
+ // Verify that each handler chose a unique point
+ QVERIFY(!pointIndexPerHandler.contains(chosenPointIndex));
+ pointIndexPerHandler.append(chosenPointIndex);
+ QPoint point = points[chosenPointIndex];
+ QCOMPARE(h->point().scenePosition().toPoint(), point);
+ QCOMPARE(h->point().pressedButtons(), Qt::NoButton);
+ QCOMPARE(h->translation(), QVector2D());
+ QCOMPARE(translationSpies[i]->count(), 1);
+ ++i;
+ }
+
+ for (int i = 0; i < 3; ++i)
+ points[i] += QPoint(10 + 10 * i, 10 + 10 * i % 2);
+ QTest::touchEvent(window, touchDevice).move(1, points[0], window).move(2, points[1], window).move(3, points[2], window);
+ QQuickTouchUtils::flush(window);
+ i = 0;
+ for (auto h : handlers) {
+ QCOMPARE(h->active(), true);
+ QCOMPARE(activeSpies[i]->count(), 1);
+ QCOMPARE(pointSpies[i]->count(), 2);
+ QCOMPARE(h->point().position().toPoint(), points[pointIndexPerHandler[i]]);
+ QCOMPARE(h->point().scenePosition().toPoint(), points[pointIndexPerHandler[i]]);
+ QCOMPARE(h->point().pressPosition().toPoint(), pressPoints[pointIndexPerHandler[i]]);
+ QCOMPARE(h->point().scenePressPosition().toPoint(), pressPoints[pointIndexPerHandler[i]]);
+ QCOMPARE(h->point().pressedButtons(), Qt::NoButton);
+ QVERIFY(h->point().velocity().x() > 0);
+ QVERIFY(h->point().velocity().y() > 0);
+ QCOMPARE(h->translation(), QVector2D(10 + 10 * pointIndexPerHandler[i], 10 + 10 * pointIndexPerHandler[i] % 2));
+ QCOMPARE(translationSpies[i]->count(), 2);
+ ++i;
+ }
+
+ QTest::touchEvent(window, touchDevice).release(1, points[0], window).release(2, points[1], window).release(3, points[2], window);
+ QQuickTouchUtils::flush(window);
+ i = 0;
+ for (auto h : handlers) {
+ QTRY_COMPARE(h->active(), false);
+ QCOMPARE(activeSpies[i]->count(), 2);
+ QCOMPARE(pointSpies[i]->count(), 3);
+ QCOMPARE(h->translation(), QVector2D());
+ QCOMPARE(translationSpies[i]->count(), 3);
+ ++i;
+ }
+
+ qDeleteAll(activeSpies);
+ qDeleteAll(pointSpies);
+ qDeleteAll(translationSpies);
+}
+
+void tst_PointHandler::pressedMultipleButtons_data()
+{
+ QTest::addColumn<Qt::MouseButtons>("accepted");
+ QTest::addColumn<QList<Qt::MouseButtons> >("buttons");
+ QTest::addColumn<QList<bool> >("active");
+ QTest::addColumn<QList<Qt::MouseButtons> >("pressedButtons");
+ QTest::addColumn<int>("changeCount");
+
+ QList<Qt::MouseButtons> buttons;
+ QList<bool> active;
+ QList<Qt::MouseButtons> pressedButtons;
+ buttons << Qt::LeftButton
+ << (Qt::LeftButton | Qt::RightButton)
+ << Qt::LeftButton
+ << Qt::NoButton;
+ active << true
+ << true
+ << true
+ << false;
+ pressedButtons << Qt::LeftButton
+ << (Qt::LeftButton | Qt::RightButton)
+ << Qt::LeftButton
+ << Qt::NoButton;
+ QTest::newRow("Accept Left - Press left, Press Right, Release Right")
+ << Qt::MouseButtons(Qt::LeftButton) << buttons << active << pressedButtons << 4;
+
+ buttons.clear();
+ active.clear();
+ pressedButtons.clear();
+ buttons << Qt::LeftButton
+ << (Qt::LeftButton | Qt::RightButton)
+ << Qt::RightButton
+ << Qt::NoButton;
+ active << true
+ << true
+ << false
+ << false;
+ pressedButtons << Qt::LeftButton
+ << (Qt::LeftButton | Qt::RightButton)
+ << Qt::NoButton // Not the "truth" but filtered according to this handler's acceptedButtons
+ << Qt::NoButton;
+ QTest::newRow("Accept Left - Press left, Press Right, Release Left")
+ << Qt::MouseButtons(Qt::LeftButton) << buttons << active << pressedButtons << 3;
+
+ buttons.clear();
+ active.clear();
+ pressedButtons.clear();
+ buttons << Qt::LeftButton
+ << (Qt::LeftButton | Qt::RightButton)
+ << Qt::LeftButton
+ << Qt::NoButton;
+ active << true
+ << true
+ << true
+ << false;
+ pressedButtons << Qt::LeftButton
+ << (Qt::LeftButton | Qt::RightButton)
+ << Qt::LeftButton
+ << Qt::NoButton;
+ QTest::newRow("Accept Left|Right - Press left, Press Right, Release Right")
+ << (Qt::LeftButton | Qt::RightButton) << buttons << active << pressedButtons << 4;
+
+ buttons.clear();
+ active.clear();
+ pressedButtons.clear();
+ buttons << Qt::RightButton
+ << (Qt::LeftButton | Qt::RightButton)
+ << Qt::LeftButton
+ << Qt::NoButton;
+ active << true
+ << true
+ << false
+ << false;
+ pressedButtons << Qt::RightButton
+ << (Qt::LeftButton | Qt::RightButton)
+ << Qt::NoButton // Not the "truth" but filtered according to this handler's acceptedButtons
+ << Qt::NoButton;
+ QTest::newRow("Accept Right - Press Right, Press Left, Release Right")
+ << Qt::MouseButtons(Qt::RightButton) << buttons << active << pressedButtons << 3;
+}
+
+void tst_PointHandler::pressedMultipleButtons()
+{
+ QFETCH(Qt::MouseButtons, accepted);
+ QFETCH(QList<Qt::MouseButtons>, buttons);
+ QFETCH(QList<bool>, active);
+ QFETCH(QList<Qt::MouseButtons>, pressedButtons);
+ QFETCH(int, changeCount);
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "pointTracker.qml");
+ QQuickView * window = windowPtr.data();
+ QQuickItem *tracker = window->rootObject()->findChild<QQuickItem *>("pointTracker");
+ QVERIFY(tracker);
+ QQuickPointHandler *handler = window->rootObject()->findChild<QQuickPointHandler *>("pointHandler");
+ QVERIFY(handler);
+
+ QSignalSpy activeSpy(handler, SIGNAL(activeChanged()));
+ QSignalSpy pointSpy(handler, SIGNAL(pointChanged()));
+ handler->setAcceptedButtons(accepted);
+
+ QPoint point(100,100);
+
+ for (int i = 0; i < buttons.count(); ++i) {
+ int btns = int(buttons.at(i));
+ int release = 0;
+ if (i > 0) {
+ int lastBtns = int(buttons.at(i - 1));
+ release = lastBtns & ~btns;
+ }
+ if (release)
+ QTest::mouseRelease(windowPtr.data(), Qt::MouseButton(release), Qt::NoModifier, point);
+ else
+ QTest::mousePress(windowPtr.data(), Qt::MouseButton(btns), Qt::NoModifier, point);
+
+ qCDebug(lcPointerTests) << i << ": acceptedButtons" << handler->acceptedButtons()
+ << "; comparing" << handler->point().pressedButtons() << pressedButtons.at(i);
+ QCOMPARE(handler->point().pressedButtons(), pressedButtons.at(i));
+ QCOMPARE(handler->active(), active.at(i));
+ }
+
+ QTest::mousePress(windowPtr.data(), Qt::NoButton, Qt::NoModifier, point);
+ QCOMPARE(handler->active(), false);
+ QCOMPARE(activeSpy.count(), 2);
+ QCOMPARE(pointSpy.count(), changeCount);
+}
+
+QTEST_MAIN(tst_PointHandler)
+
+#include "tst_qquickpointhandler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
new file mode 100644
index 0000000000..221e7df139
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ property alias label: label.text
+ property alias pressed: tap.pressed
+ property bool checked: false
+ property alias gesturePolicy: tap.gesturePolicy
+ signal tapped
+ signal canceled
+
+ width: label.implicitWidth * 1.5; height: label.implicitHeight * 2.0
+ border.color: "#9f9d9a"; border.width: 1; radius: height / 4; antialiasing: true
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: tap.pressed ? "#b8b5b2" : "#efebe7" }
+ GradientStop { position: 1.0; color: "#b8b5b2" }
+ }
+
+ TapHandler {
+ id: tap
+ objectName: label.text
+ longPressThreshold: 100 // CI can be insanely slow, so don't demand a timely release to generate onTapped
+ onTapped: {
+ tapFlash.start()
+ root.tapped()
+ }
+ onCanceled: root.canceled()
+ }
+
+ Text {
+ id: label
+ font.pointSize: 14
+ text: "Button"
+ anchors.centerIn: parent
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: "transparent"
+ border.width: 2; radius: root.radius; antialiasing: true
+ opacity: tapFlash.running ? 1 : 0
+ FlashAnimation on visible { id: tapFlash }
+ }
+
+ Rectangle {
+ objectName: "expandingCircle"
+ radius: tap.timeHeld * 100
+ visible: radius > 0 && tap.pressed
+ border.width: 3
+ border.color: "blue"
+ color: "transparent"
+ width: radius * 2
+ height: radius * 2
+ x: tap.point.scenePressPosition.x - radius
+ y: tap.point.scenePressPosition.y - radius
+ opacity: 0.25
+ Component.onCompleted: parent = root.parent
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
new file mode 100644
index 0000000000..158a02b7a6
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+SequentialAnimation {
+ id: tapFlash
+ running: false
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: false }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: true }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
new file mode 100644
index 0000000000..4a8b8e1375
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ width: 320
+ height: 240
+ Button {
+ id: button
+ objectName: "Overridden"
+ label: "Overridden"
+ x: 10; y: 10; width: parent.width - 20; height: 40
+ TapHandler {
+ gesturePolicy: TapHandler.ReleaseWithinBounds
+ objectName: "override"
+ onTapped: button.tapped()
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
new file mode 100644
index 0000000000..821b8073e9
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ width: 320
+ height: 240
+ Button {
+ objectName: "DragThreshold"
+ label: "DragThreshold"
+ x: 10; y: 10; width: parent.width - 20; height: 40
+ gesturePolicy: TapHandler.DragThreshold
+ }
+ Button {
+ objectName: "WithinBounds"
+ label: "WithinBounds"
+ x: 10; y: 60; width: parent.width - 20; height: 40
+ gesturePolicy: TapHandler.WithinBounds
+ }
+ Button {
+ objectName: "ReleaseWithinBounds"
+ label: "ReleaseWithinBounds"
+ x: 10; y: 110; width: parent.width - 20; height: 40
+ gesturePolicy: TapHandler.ReleaseWithinBounds
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
new file mode 100644
index 0000000000..aea01c154c
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Rectangle {
+ width: 320
+ height: 240
+ color: rightTap.pressed ? "tomato" : "beige"
+ TapHandler {
+ id: rightTap
+ objectName: "right button TapHandler"
+ longPressThreshold: 0.5
+ acceptedButtons: Qt.RightButton
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/qquicktaphandler.pro b/tests/auto/quick/pointerhandlers/qquicktaphandler/qquicktaphandler.pro
new file mode 100644
index 0000000000..b41a94b55e
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/qquicktaphandler.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+
+TARGET = tst_qquicktaphandler
+QT += core-private gui-private qml-private quick-private testlib
+
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qquicktaphandler.cpp
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+# OTHER_FILES += data/foo.qml
+
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
new file mode 100644
index 0000000000..33cea69147
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -0,0 +1,721 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtGui/qstylehints.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickpointerhandler_p.h>
+#include <QtQuick/private/qquicktaphandler_p.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <private/qquickwindow_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlproperty.h>
+
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+class tst_TapHandler : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_TapHandler()
+ :touchDevice(QTest::createTouchDevice())
+ {}
+
+private slots:
+ void initTestCase();
+
+ void touchGesturePolicyDragThreshold();
+ void mouseGesturePolicyDragThreshold();
+ void touchMouseGesturePolicyDragThreshold();
+ void touchGesturePolicyWithinBounds();
+ void mouseGesturePolicyWithinBounds();
+ void touchGesturePolicyReleaseWithinBounds();
+ void mouseGesturePolicyReleaseWithinBounds();
+ void touchMultiTap();
+ void mouseMultiTap();
+ void touchLongPress();
+ void mouseLongPress();
+ void buttonsMultiTouch();
+ void componentUserBehavioralOverride();
+ void rightLongPressIgnoreWheel();
+
+private:
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+ QTouchDevice *touchDevice;
+};
+
+void tst_TapHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+{
+ window.reset(new QQuickView);
+ window->setSource(testFileUrl(fileName));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+}
+
+void tst_TapHandler::initTestCase()
+{
+ // This test assumes that we don't get synthesized mouse events from QGuiApplication
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
+
+ QQmlDataTest::initTestCase();
+}
+
+void tst_TapHandler::touchGesturePolicyDragThreshold()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *buttonDragThreshold = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(buttonDragThreshold);
+ QSignalSpy dragThresholdTappedSpy(buttonDragThreshold, SIGNAL(tapped()));
+
+ // DragThreshold button stays pressed while touchpoint stays within dragThreshold, emits tapped on release
+ QPoint p1 = buttonDragThreshold->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
+ QCOMPARE(dragThresholdTappedSpy.count(), 1);
+
+ // DragThreshold button is no longer pressed if touchpoint goes beyond dragThreshold
+ dragThresholdTappedSpy.clear();
+ p1 = buttonDragThreshold->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+ p1 += QPoint(1, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!buttonDragThreshold->property("pressed").toBool());
+ QCOMPARE(dragThresholdTappedSpy.count(), 0);
+}
+
+void tst_TapHandler::mouseGesturePolicyDragThreshold()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *buttonDragThreshold = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(buttonDragThreshold);
+ QSignalSpy dragThresholdTappedSpy(buttonDragThreshold, SIGNAL(tapped()));
+
+ // DragThreshold button stays pressed while mouse stays within dragThreshold, emits tapped on release
+ QPoint p1 = buttonDragThreshold->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
+ QTRY_COMPARE(dragThresholdTappedSpy.count(), 1);
+
+ // DragThreshold button is no longer pressed if mouse goes beyond dragThreshold
+ dragThresholdTappedSpy.clear();
+ p1 = buttonDragThreshold->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+ p1 += QPoint(1, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(!buttonDragThreshold->property("pressed").toBool());
+ QCOMPARE(dragThresholdTappedSpy.count(), 0);
+}
+
+void tst_TapHandler::touchMouseGesturePolicyDragThreshold()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *buttonDragThreshold = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(buttonDragThreshold);
+ QSignalSpy tappedSpy(buttonDragThreshold, SIGNAL(tapped()));
+ QSignalSpy canceledSpy(buttonDragThreshold, SIGNAL(canceled()));
+
+ // Press mouse, drag it outside the button, release
+ QPoint p1 = buttonDragThreshold->mapToScene(QPointF(20, 20)).toPoint();
+ QPoint p2 = p1 + QPoint(int(buttonDragThreshold->height()), 0);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ QTest::mouseMove(window, p2);
+ QTRY_COMPARE(canceledSpy.count(), 1);
+ QCOMPARE(tappedSpy.count(), 0);
+ QCOMPARE(buttonDragThreshold->property("pressed").toBool(), false);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p2);
+
+ // Press and release touch, verify that it still works (QTBUG-71466)
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 1);
+
+ // Press touch, drag it outside the button, release
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_COMPARE(buttonDragThreshold->property("pressed").toBool(), false);
+ QTest::touchEvent(window, touchDevice).release(1, p2, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_COMPARE(canceledSpy.count(), 2);
+ QCOMPARE(tappedSpy.count(), 1); // didn't increase
+ QCOMPARE(buttonDragThreshold->property("pressed").toBool(), false);
+
+ // Press and release mouse, verify that it still works
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(tappedSpy.count(), 2);
+ QCOMPARE(canceledSpy.count(), 2); // didn't increase
+ QCOMPARE(buttonDragThreshold->property("pressed").toBool(), false);
+}
+
+void tst_TapHandler::touchGesturePolicyWithinBounds()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *buttonWithinBounds = window->rootObject()->findChild<QQuickItem*>("WithinBounds");
+ QVERIFY(buttonWithinBounds);
+ QSignalSpy withinBoundsTappedSpy(buttonWithinBounds, SIGNAL(tapped()));
+
+ // WithinBounds button stays pressed while touchpoint stays within bounds, emits tapped on release
+ QPoint p1 = buttonWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonWithinBounds->property("pressed").toBool());
+ p1 += QPoint(50, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
+ QCOMPARE(withinBoundsTappedSpy.count(), 1);
+
+ // WithinBounds button is no longer pressed if touchpoint leaves bounds
+ withinBoundsTappedSpy.clear();
+ p1 = buttonWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonWithinBounds->property("pressed").toBool());
+ p1 += QPoint(0, 100);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(!buttonWithinBounds->property("pressed").toBool());
+ QCOMPARE(withinBoundsTappedSpy.count(), 0);
+}
+
+void tst_TapHandler::mouseGesturePolicyWithinBounds()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *buttonWithinBounds = window->rootObject()->findChild<QQuickItem*>("WithinBounds");
+ QVERIFY(buttonWithinBounds);
+ QSignalSpy withinBoundsTappedSpy(buttonWithinBounds, SIGNAL(tapped()));
+
+ // WithinBounds button stays pressed while touchpoint stays within bounds, emits tapped on release
+ QPoint p1 = buttonWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(buttonWithinBounds->property("pressed").toBool());
+ p1 += QPoint(50, 0);
+ QTest::mouseMove(window, p1);
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
+ QCOMPARE(withinBoundsTappedSpy.count(), 1);
+
+ // WithinBounds button is no longer pressed if touchpoint leaves bounds
+ withinBoundsTappedSpy.clear();
+ p1 = buttonWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(buttonWithinBounds->property("pressed").toBool());
+ p1 += QPoint(0, 100);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(!buttonWithinBounds->property("pressed").toBool());
+ QCOMPARE(withinBoundsTappedSpy.count(), 0);
+}
+
+void tst_TapHandler::touchGesturePolicyReleaseWithinBounds()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *buttonReleaseWithinBounds = window->rootObject()->findChild<QQuickItem*>("ReleaseWithinBounds");
+ QVERIFY(buttonReleaseWithinBounds);
+ QSignalSpy releaseWithinBoundsTappedSpy(buttonReleaseWithinBounds, SIGNAL(tapped()));
+
+ // ReleaseWithinBounds button stays pressed while touchpoint wanders anywhere,
+ // then if it comes back within bounds, emits tapped on release
+ QPoint p1 = buttonReleaseWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ p1 += QPoint(50, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ p1 += QPoint(250, 100);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ p1 = buttonReleaseWithinBounds->mapToScene(QPointF(25, 15)).toPoint();
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
+ QCOMPARE(releaseWithinBoundsTappedSpy.count(), 1);
+
+ // ReleaseWithinBounds button does not emit tapped if released out of bounds
+ releaseWithinBoundsTappedSpy.clear();
+ p1 = buttonReleaseWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ p1 += QPoint(0, 100);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
+ QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
+}
+
+void tst_TapHandler::mouseGesturePolicyReleaseWithinBounds()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *buttonReleaseWithinBounds = window->rootObject()->findChild<QQuickItem*>("ReleaseWithinBounds");
+ QVERIFY(buttonReleaseWithinBounds);
+ QSignalSpy releaseWithinBoundsTappedSpy(buttonReleaseWithinBounds, SIGNAL(tapped()));
+
+ // ReleaseWithinBounds button stays pressed while touchpoint wanders anywhere,
+ // then if it comes back within bounds, emits tapped on release
+ QPoint p1 = buttonReleaseWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ p1 += QPoint(50, 0);
+ QTest::mouseMove(window, p1);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ p1 += QPoint(250, 100);
+ QTest::mouseMove(window, p1);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ p1 = buttonReleaseWithinBounds->mapToScene(QPointF(25, 15)).toPoint();
+ QTest::mouseMove(window, p1);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
+ QCOMPARE(releaseWithinBoundsTappedSpy.count(), 1);
+
+ // ReleaseWithinBounds button does not emit tapped if released out of bounds
+ releaseWithinBoundsTappedSpy.clear();
+ p1 = buttonReleaseWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ p1 += QPoint(0, 100);
+ QTest::mouseMove(window, p1);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
+ QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
+}
+
+void tst_TapHandler::touchMultiTap()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(button);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+
+ // Tap once
+ QPoint p1 = button->mapToScene(QPointF(2, 2)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 1);
+
+ // Tap again in exactly the same place (not likely with touch in the real world)
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 2);
+
+ // Tap a third time, nearby
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 3);
+
+ // Tap a fourth time, drifting farther away
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 4);
+}
+
+void tst_TapHandler::mouseMultiTap()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(button);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+
+ // Tap once
+ QPoint p1 = button->mapToScene(QPointF(2, 2)).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 1);
+
+ // Tap again in exactly the same place (not likely with touch in the real world)
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 2);
+
+ // Tap a third time, nearby
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 3);
+
+ // Tap a fourth time, drifting farther away
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 4);
+}
+
+void tst_TapHandler::touchLongPress()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(button);
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>("DragThreshold");
+ QVERIFY(tapHandler);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+ QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged()));
+ QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged()));
+ QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed()));
+
+ // Reduce the threshold so that we can get a long press quickly
+ tapHandler->setLongPressThreshold(0.5);
+ QCOMPARE(longPressThresholdChangedSpy.count(), 1);
+
+ // Press and hold
+ QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTRY_COMPARE(longPressedSpy.count(), 1);
+ timeHeldSpy.wait(); // the longer we hold it, the more this will occur
+ qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.count() << "times";
+ QVERIFY(timeHeldSpy.count() > 0);
+ QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere
+
+ // Release and verify that tapped was not emitted
+ QTest::touchEvent(window, touchDevice).release(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 0);
+}
+
+void tst_TapHandler::mouseLongPress()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(button);
+ QQuickTapHandler *tapHandler = button->findChild<QQuickTapHandler*>("DragThreshold");
+ QVERIFY(tapHandler);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+ QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged()));
+ QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged()));
+ QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed()));
+
+ // Reduce the threshold so that we can get a long press quickly
+ tapHandler->setLongPressThreshold(0.5);
+ QCOMPARE(longPressThresholdChangedSpy.count(), 1);
+
+ // Press and hold
+ QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(button->property("pressed").toBool());
+ QTRY_COMPARE(longPressedSpy.count(), 1);
+ timeHeldSpy.wait(); // the longer we hold it, the more this will occur
+ qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.count() << "times";
+ QVERIFY(timeHeldSpy.count() > 0);
+ QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere
+
+ // Release and verify that tapped was not emitted
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 500);
+ QTRY_VERIFY(!button->property("pressed").toBool());
+ QCOMPARE(tappedSpy.count(), 0);
+}
+
+void tst_TapHandler::buttonsMultiTouch()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttons.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *buttonDragThreshold = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
+ QVERIFY(buttonDragThreshold);
+ QSignalSpy dragThresholdTappedSpy(buttonDragThreshold, SIGNAL(tapped()));
+
+ QQuickItem *buttonWithinBounds = window->rootObject()->findChild<QQuickItem*>("WithinBounds");
+ QVERIFY(buttonWithinBounds);
+ QSignalSpy withinBoundsTappedSpy(buttonWithinBounds, SIGNAL(tapped()));
+
+ QQuickItem *buttonReleaseWithinBounds = window->rootObject()->findChild<QQuickItem*>("ReleaseWithinBounds");
+ QVERIFY(buttonReleaseWithinBounds);
+ QSignalSpy releaseWithinBoundsTappedSpy(buttonReleaseWithinBounds, SIGNAL(tapped()));
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
+
+ // can press multiple buttons at the same time
+ QPoint p1 = buttonDragThreshold->mapToScene(QPointF(20, 20)).toPoint();
+ touchSeq.press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ QPoint p2 = buttonWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ touchSeq.stationary(1).press(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonWithinBounds->property("pressed").toBool());
+ QPoint p3 = buttonReleaseWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
+ touchSeq.stationary(1).stationary(2).press(3, p3, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+
+ // can release top button and press again: others stay pressed the whole time
+ touchSeq.stationary(2).stationary(3).release(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
+ QCOMPARE(dragThresholdTappedSpy.count(), 1);
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QCOMPARE(withinBoundsTappedSpy.count(), 0);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
+ touchSeq.stationary(2).stationary(3).press(1, p1, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+
+ // can release middle button and press again: others stay pressed the whole time
+ touchSeq.stationary(1).stationary(3).release(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(!buttonWithinBounds->property("pressed").toBool());
+ QCOMPARE(withinBoundsTappedSpy.count(), 1);
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+ QCOMPARE(dragThresholdTappedSpy.count(), 1);
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QCOMPARE(releaseWithinBoundsTappedSpy.count(), 0);
+ touchSeq.stationary(1).stationary(3).press(2, p2, window).commit();
+ QQuickTouchUtils::flush(window);
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+
+ // can release bottom button and press again: others stay pressed the whole time
+ touchSeq.stationary(1).stationary(2).release(3, p3, window).commit();
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(releaseWithinBoundsTappedSpy.count(), 1);
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QCOMPARE(withinBoundsTappedSpy.count(), 1);
+ QVERIFY(!buttonReleaseWithinBounds->property("pressed").toBool());
+ QCOMPARE(dragThresholdTappedSpy.count(), 1);
+ touchSeq.stationary(1).stationary(2).press(3, p3, window).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(buttonDragThreshold->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+}
+
+void tst_TapHandler::componentUserBehavioralOverride()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "buttonOverrideHandler.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *button = window->rootObject()->findChild<QQuickItem*>("Overridden");
+ QVERIFY(button);
+ QQuickTapHandler *innerTapHandler = button->findChild<QQuickTapHandler*>("Overridden");
+ QVERIFY(innerTapHandler);
+ QQuickTapHandler *userTapHandler = button->findChild<QQuickTapHandler*>("override");
+ QVERIFY(userTapHandler);
+ QSignalSpy tappedSpy(button, SIGNAL(tapped()));
+ QSignalSpy innerGrabChangedSpy(innerTapHandler, SIGNAL(grabChanged(QQuickEventPoint::GrabTransition, QQuickEventPoint *)));
+ QSignalSpy userGrabChangedSpy(userTapHandler, SIGNAL(grabChanged(QQuickEventPoint::GrabTransition, QQuickEventPoint *)));
+ QSignalSpy innerPressedChangedSpy(innerTapHandler, SIGNAL(pressedChanged()));
+ QSignalSpy userPressedChangedSpy(userTapHandler, SIGNAL(pressedChanged()));
+
+ // Press
+ QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(userPressedChangedSpy.count(), 1);
+ QCOMPARE(innerPressedChangedSpy.count(), 0);
+ QCOMPARE(innerGrabChangedSpy.count(), 0);
+ QCOMPARE(userGrabChangedSpy.count(), 1);
+
+ // Release
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(userPressedChangedSpy.count(), 2);
+ QCOMPARE(innerPressedChangedSpy.count(), 0);
+ QCOMPARE(tappedSpy.count(), 1); // only because the override handler makes that happen
+ QCOMPARE(innerGrabChangedSpy.count(), 0);
+ QCOMPARE(userGrabChangedSpy.count(), 2);
+}
+
+void tst_TapHandler::rightLongPressIgnoreWheel()
+{
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "rightTapHandler.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickTapHandler *tap = window->rootObject()->findChild<QQuickTapHandler*>();
+ QVERIFY(tap);
+ QSignalSpy tappedSpy(tap, SIGNAL(tapped(QQuickEventPoint *)));
+ QSignalSpy longPressedSpy(tap, SIGNAL(longPressed()));
+ QPoint p1(100, 100);
+
+ // Mouse wheel with ScrollBegin phase (because as soon as two fingers are touching
+ // the trackpad, it will send such an event: QTBUG-71955)
+ {
+ QWheelEvent wheelEvent(p1, p1, QPoint(0, 0), QPoint(0, 0),
+ Qt::NoButton, Qt::NoModifier, Qt::ScrollBegin, false, Qt::MouseEventNotSynthesized);
+ QGuiApplication::sendEvent(window, &wheelEvent);
+ }
+
+ // Press
+ QTest::mousePress(window, Qt::RightButton, Qt::NoModifier, p1);
+ QTRY_COMPARE(tap->isPressed(), true);
+
+ // Mouse wheel ScrollEnd phase
+ QWheelEvent wheelEvent(p1, p1, QPoint(0, 0), QPoint(0, 0),
+ Qt::NoButton, Qt::NoModifier, Qt::ScrollEnd, false, Qt::MouseEventNotSynthesized);
+ QGuiApplication::sendEvent(window, &wheelEvent);
+ QTRY_COMPARE(longPressedSpy.count(), 1);
+ QCOMPARE(tap->isPressed(), true);
+ QCOMPARE(tappedSpy.count(), 0);
+
+ // Release
+ QTest::mouseRelease(window, Qt::RightButton, Qt::NoModifier, p1, 500);
+ QTRY_COMPARE(tap->isPressed(), false);
+ QCOMPARE(tappedSpy.count(), 0);
+}
+
+QTEST_MAIN(tst_TapHandler)
+
+#include "tst_qquicktaphandler.moc"
+
diff --git a/tests/auto/quick/propertyrequirements/propertyrequirements.pro b/tests/auto/quick/propertyrequirements/propertyrequirements.pro
new file mode 100644
index 0000000000..8fe574e0bf
--- /dev/null
+++ b/tests/auto/quick/propertyrequirements/propertyrequirements.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase
+TARGET = tst_propertyrequirements
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_propertyrequirements.cpp
+
+QT += qml-private testlib
diff --git a/tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp b/tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp
new file mode 100644
index 0000000000..5781a007b6
--- /dev/null
+++ b/tests/auto/quick/propertyrequirements/tst_propertyrequirements.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Kevin Krammer <kevin.krammer@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/private/qqmlmetatype_p.h>
+#include <QtCore/QDebug>
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+
+class tst_PropertyRequirements : public QObject
+{
+ Q_OBJECT
+public:
+ tst_PropertyRequirements();
+
+private slots:
+ void constantOrNotifyableMain();
+ void constantOrNotifyableFull();
+
+private:
+ typedef QList<QQmlType> Failures;
+
+ /*!
+ All properties that do not pass the check and the affected QML types
+
+ Key: Property name formatted as C++-class-name::property-name
+ Value: List of QQmlType which have the property
+ */
+ typedef QHash<QString, Failures> FailuresByProperty;
+
+ enum TestDepth {
+ MainTypeOnly, //! Check only the properties of the main C++ type for each QML type
+ WithSuperClasses //! Check the super classes for each C++ type as well
+ };
+
+ void testAllQmlTypes(TestDepth testDepth, FailuresByProperty &failuresByProperty);
+ void testQmlType(TestDepth testDepth, const QQmlType &qmlType, FailuresByProperty &failuresByProperty);
+};
+
+
+tst_PropertyRequirements::tst_PropertyRequirements()
+{
+}
+
+void tst_PropertyRequirements::constantOrNotifyableMain()
+{
+ FailuresByProperty failuresByProperty;
+
+ // test
+ testAllQmlTypes(MainTypeOnly, failuresByProperty);
+
+ // report
+ QHash<QString, QStringList> occurrences;
+ for (auto it = failuresByProperty.constBegin(); it != failuresByProperty.constEnd(); ++it) {
+
+ occurrences[it.value().at(0).qmlTypeName()].append(it.key());
+ }
+
+ QStringList messages;
+ for (auto it = occurrences.constBegin(); it != occurrences.constEnd(); ++it) {
+ const QString occurrencePattern("%1:\n\t%2");
+
+ QStringList properties = it.value();
+ properties.sort();
+ messages.append(occurrencePattern.arg(it.key(), properties.join("\n\t")));
+ }
+ messages.sort();
+
+ const QString message("\nThe following QML Types have properties which are neither CONSTANT nor NOTIFYable:\n");
+ QWARN(qPrintable(message + messages.join("\n")));
+
+ // TODO enable once technical debt is fixes
+ // QCOMPARE(failuresByProperty.count(), 0);
+}
+
+void tst_PropertyRequirements::constantOrNotifyableFull()
+{
+ FailuresByProperty failuresByProperty;
+
+ // test
+ testAllQmlTypes(WithSuperClasses, failuresByProperty);
+
+ // report
+ QStringList messages;
+ for (auto it = failuresByProperty.constBegin(); it != failuresByProperty.constEnd(); ++it) {
+
+ QSet<QString> occurrences;
+ for (const QQmlType &qmlType : it.value()) {
+ static const QString occurrencePattern("%1 (%2)");
+
+ occurrences.insert(occurrencePattern.arg(qmlType.metaObject()->className(),
+ qmlType.qmlTypeName()));
+
+ }
+
+ static const QString messagePattern("\nProperty %1 neither CONSTANT nor NOTIFYable. Affected types:\n\t%2");
+ QStringList occurrencesList = occurrences.toList();
+ occurrencesList.sort();
+ messages.append(messagePattern.arg(it.key(), occurrencesList.join("\n\t")));
+
+ }
+ messages.sort();
+
+ QWARN(qPrintable(messages.join("\n")));
+
+ // TODO enable once technical debt is fixes
+ // QCOMPARE(failuresByProperty.count(), 0);
+}
+
+void tst_PropertyRequirements::testAllQmlTypes(TestDepth testDepth, FailuresByProperty &failuresByProperty)
+{
+ const QVector<QByteArray> qmlData {
+ "import QtQml 2.2\nQtObject {}",
+ "import QtQml.Models 2.2\nListModel {}",
+ "import QtQuick 2.5\nItem {}",
+ "import QtQuick.Window 2.2\nWindow {}",
+ "import QtQuick.Dialogs 1.2\nDialog {}",
+ "import QtQuick.Layouts 1.2\nGridLayout {}",
+ "import QtQuick.Controls 2.2\nButton {}",
+ "import QtQuick.Templates 2.2\nButton {}"
+ };
+
+ QQmlEngine engine;
+ QSet<QString> seenTypes;
+
+ for (const QByteArray &data : qmlData) {
+ QQmlComponent component(&engine);
+ component.setData(data, QUrl());
+
+ for (const QQmlType &qmlType : QQmlMetaType::qmlTypes()) {
+ if (!seenTypes.contains(qmlType.qmlTypeName())) {
+ testQmlType(testDepth, qmlType, failuresByProperty);
+ }
+ }
+ seenTypes.unite(QSet<QString>::fromList(QQmlMetaType::qmlTypeNames()));
+ }
+}
+
+void tst_PropertyRequirements::testQmlType(TestDepth testDepth, const QQmlType &qmlType, FailuresByProperty &failuresByProperty)
+{
+ QList<const QMetaObject*> inheritanceHierarchy;
+
+ const QMetaObject *mo = qmlType.metaObject();
+ while (mo) {
+ inheritanceHierarchy.prepend(mo);
+ mo = mo->superClass();
+ }
+
+ // check if this type is derived from QObject and even can have signals
+ // i.e. weed out the Q_GADGET classes
+ if (inheritanceHierarchy.isEmpty()
+ || inheritanceHierarchy.constFirst()->className() != QByteArrayLiteral("QObject")) {
+ return;
+ }
+
+ if (testDepth == MainTypeOnly) {
+ inheritanceHierarchy.clear();
+ inheritanceHierarchy.append(qmlType.metaObject());
+ }
+
+ for (const QMetaObject *metaClass : qAsConst(inheritanceHierarchy)) {
+ for (int idx = metaClass->propertyOffset(); idx < metaClass->propertyCount(); ++idx) {
+ const QMetaProperty property = metaClass->property(idx);
+
+ // needs to be either CONSTANT or have a NOTIFY signal
+ if (!property.isConstant() && !property.hasNotifySignal()) {
+ static const QString fullNamePattern("%1::%2");
+ const QString fullPropertyName = fullNamePattern.arg(metaClass->className(), property.name());
+
+ failuresByProperty[fullPropertyName].append(qmlType);
+ }
+ }
+ }
+}
+
+QTEST_MAIN(tst_PropertyRequirements)
+
+#include "tst_propertyrequirements.moc"
diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
index e843f9e5a1..1bfeb94161 100644
--- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
+++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
@@ -42,9 +42,11 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
#include <QtQuick/private/qquickaccessibleattached_p.h>
+#include <QtQuick/private/qquicklistview_p.h>
+#include <QtQuick/private/qquicktext_p.h>
#include "../../shared/util.h"
-
+#include "../shared/visualtestutil.h"
#define EXPECT(cond) \
do { \
@@ -143,7 +145,7 @@ void tst_QQuickAccessible::commonTests()
view->setSource(testFileUrl(accessibleRoleFileName));
view->show();
// view->setFocus();
- QVERIFY(view->rootObject() != 0);
+ QVERIFY(view->rootObject() != nullptr);
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(view);
QVERIFY(iface);
@@ -160,10 +162,10 @@ void tst_QQuickAccessible::quickAttachedProperties()
component.setData("import QtQuick 2.0\nItem {\n"
"}", QUrl());
QObject *object = component.create();
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
- QCOMPARE(attachedObject, static_cast<QObject*>(0));
+ QCOMPARE(attachedObject, static_cast<QObject*>(nullptr));
delete object;
}
@@ -181,7 +183,7 @@ void tst_QQuickAccessible::quickAttachedProperties()
"Accessible.role: Accessible.Button\n"
"}", QUrl());
QObject *object = component.create();
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
QVERIFY(attachedObject);
@@ -207,7 +209,7 @@ void tst_QQuickAccessible::quickAttachedProperties()
"Accessible.description: \"Duck\"\n"
"}", QUrl());
QObject *object = component.create();
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
QVERIFY(attachedObject);
@@ -224,6 +226,72 @@ void tst_QQuickAccessible::quickAttachedProperties()
}
delete object;
}
+
+ // Check overriding of attached role for Text
+ {
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nText {\n"
+ "Accessible.role: Accessible.Button\n"
+ "Accessible.name: \"TextButton\"\n"
+ "Accessible.description: \"Text Button\"\n"
+ "}", QUrl());
+ QObject *object = component.create();
+ QVERIFY(object != nullptr);
+
+ QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
+ QVERIFY(attachedObject);
+ if (attachedObject) {
+ QVariant p = attachedObject->property("role");
+ QCOMPARE(p.isNull(), false);
+ QCOMPARE(p.toInt(), int(QAccessible::PushButton));
+ p = attachedObject->property("name");
+ QCOMPARE(p.isNull(), false);
+ QCOMPARE(p.toString(), QLatin1String("TextButton"));
+ p = attachedObject->property("description");
+ QCOMPARE(p.isNull(), false);
+ QCOMPARE(p.toString(), QLatin1String("Text Button"));
+ }
+ delete object;
+ }
+ // Check overriding of attached role for Text
+ {
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nListView {\n"
+ "id: list\n"
+ "model: 5\n"
+ "delegate: Text {\n"
+ "objectName: \"acc_text\"\n"
+ "Accessible.role: Accessible.Button\n"
+ "Accessible.name: \"TextButton\"\n"
+ "Accessible.description: \"Text Button\"\n"
+ "}\n"
+ "}", QUrl());
+ QObject *object = component.create();
+ QVERIFY(object != nullptr);
+
+ QQuickListView *listview = qobject_cast<QQuickListView *>(object);
+ QVERIFY(listview != nullptr);
+ QQuickItem *contentItem = listview->contentItem();
+ QQuickText *childItem = QQuickVisualTestUtil::findItem<QQuickText>(contentItem, "acc_text");
+ QVERIFY(childItem != nullptr);
+
+ QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(childItem);
+ QVERIFY(attachedObject);
+ if (attachedObject) {
+ QVariant p = attachedObject->property("role");
+ QCOMPARE(p.isNull(), false);
+ QCOMPARE(p.toInt(), int(QAccessible::PushButton));
+ p = attachedObject->property("name");
+ QCOMPARE(p.isNull(), false);
+ QCOMPARE(p.toString(), QLatin1String("TextButton"));
+ p = attachedObject->property("description");
+ QCOMPARE(p.isNull(), false);
+ QCOMPARE(p.toString(), QLatin1String("Text Button"));
+ }
+ delete object;
+ }
QTestAccessibility::clearEvents();
}
@@ -282,7 +350,7 @@ QAccessibleInterface *topLevelChildAt(QAccessibleInterface *iface, int x, int y)
{
QAccessibleInterface *child = iface->childAt(x, y);
if (!child)
- return 0;
+ return nullptr;
QAccessibleInterface *childOfChild;
while ( ( childOfChild = child->childAt(x, y)) ) {
diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
index 34b9fb6b07..8026bafb9e 100644
--- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -67,6 +67,7 @@ private slots:
void progressAndStatusChanges();
void playingAndPausedChanges();
void noCaching();
+ void sourceChangesOnFrameChanged();
};
void tst_qquickanimatedimage::cleanup()
@@ -132,6 +133,16 @@ void tst_qquickanimatedimage::frameCount()
QVERIFY(anim->isPlaying());
QCOMPARE(anim->frameCount(), 3);
+ QSignalSpy frameCountChangedSpy(anim, &QQuickAnimatedImage::frameCountChanged);
+
+ const QUrl origSource = anim->source();
+ anim->setSource(QUrl());
+ QCOMPARE(anim->frameCount(), 0);
+ QCOMPARE(frameCountChangedSpy.count(), 1);
+ anim->setSource(origSource);
+ QCOMPARE(anim->frameCount(), 3);
+ QCOMPARE(frameCountChangedSpy.count(), 2);
+
delete anim;
}
@@ -142,7 +153,7 @@ void tst_qquickanimatedimage::mirror_running()
QQuickView window;
window.setSource(testFileUrl("hearts.qml"));
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject());
QVERIFY(anim);
@@ -324,7 +335,7 @@ void tst_qquickanimatedimage::sourceSizeChanges()
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("srcImage", "");
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage*>(component.create());
- QVERIFY(anim != 0);
+ QVERIFY(anim != nullptr);
QSignalSpy sourceSizeSpy(anim, SIGNAL(sourceSizeChanged()));
@@ -387,7 +398,7 @@ void tst_qquickanimatedimage::sourceSizeChanges_intermediate()
ctxt->setContextProperty("srcImage", "");
QScopedPointer<QQuickAnimatedImage> anim(qobject_cast<QQuickAnimatedImage*>(component.create()));
- QVERIFY(anim != 0);
+ QVERIFY(anim != nullptr);
ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
@@ -412,7 +423,7 @@ void tst_qquickanimatedimage::qtbug_16520()
QQuickRectangle *root = qobject_cast<QQuickRectangle *>(component.create());
QVERIFY(root);
QQuickAnimatedImage *anim = root->findChild<QQuickAnimatedImage*>("anim");
- QVERIFY(anim != 0);
+ QVERIFY(anim != nullptr);
anim->setProperty("source", server.urlString("/stickman.gif"));
QTRY_COMPARE(anim->opacity(), qreal(0));
@@ -435,7 +446,7 @@ void tst_qquickanimatedimage::progressAndStatusChanges()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickImage::Ready);
QTRY_COMPARE(obj->progress(), 1.0);
@@ -489,7 +500,7 @@ void tst_qquickanimatedimage::playingAndPausedChanges()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickAnimatedImage *obj = qobject_cast<QQuickAnimatedImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickAnimatedImage::Null);
QTRY_VERIFY(obj->isPlaying());
QTRY_VERIFY(!obj->isPaused());
@@ -555,8 +566,8 @@ void tst_qquickanimatedimage::noCaching()
window_nocache.setSource(testFileUrl("colors_nocache.qml"));
window.show();
window_nocache.show();
- QTest::qWaitForWindowExposed(&window);
- QTest::qWaitForWindowExposed(&window_nocache);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(QTest::qWaitForWindowExposed(&window_nocache));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject());
QVERIFY(anim);
@@ -580,6 +591,33 @@ void tst_qquickanimatedimage::noCaching()
}
}
+void tst_qquickanimatedimage::sourceChangesOnFrameChanged()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("colors.qml"));
+ QVector<QQuickAnimatedImage*> images;
+
+ // Run multiple animations in parallel, this should be fast
+ for (int loops = 0; loops < 25; ++loops) {
+ QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
+
+ // QTBUG-67427: this should not produce a segfault
+ QObject::connect(anim,
+ &QQuickAnimatedImage::frameChanged,
+ [this, anim]() { anim->setSource(testFileUrl("hearts.gif")); });
+
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+
+ images.append(anim);
+ }
+
+ for (auto *anim : images)
+ QTRY_COMPARE(anim->source(), testFileUrl("hearts.gif"));
+
+ qDeleteAll(images);
+}
+
QTEST_MAIN(tst_qquickanimatedimage)
#include "tst_qquickanimatedimage.moc"
diff --git a/tests/auto/quick/qquickanimatedsprite/BLACKLIST b/tests/auto/quick/qquickanimatedsprite/BLACKLIST
new file mode 100644
index 0000000000..7eb242876a
--- /dev/null
+++ b/tests/auto/quick/qquickanimatedsprite/BLACKLIST
@@ -0,0 +1,3 @@
+# QTBUG-65613
+[test_largeAnimation]
+b2qt
diff --git a/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml b/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml
new file mode 100644
index 0000000000..551329a457
--- /dev/null
+++ b/tests/auto/quick/qquickanimatedsprite/data/infiniteLoops.qml
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+AnimatedSprite {
+ loops: AnimatedSprite.Infinite
+ source: "squarefacesprite.png"
+ frameCount: 6
+ frameDuration: 240
+ width: 160
+ height: 160
+}
diff --git a/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro b/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
index 81c73be831..a337473d99 100644
--- a/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
+++ b/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
@@ -8,7 +8,7 @@ macx:CONFIG -= app_bundle
TESTDATA = data/*
-QT += core-private gui-private qml-private quick-private network testlib
+QT += core-private gui-private qml-private quick-private network testlib qmltest
OTHER_FILES += \
- data/largeAnimation.qml
+ $$files(data/*.qml)
diff --git a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
index 820c804065..d2bbf9e6b1 100644
--- a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
+++ b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
@@ -28,9 +28,11 @@
#include <QtTest/QtTest>
#include "../../shared/util.h"
#include <QtQuick/qquickview.h>
+#include <QtQuickTest/QtQuickTest>
#include <private/qabstractanimation_p.h>
#include <private/qquickanimatedsprite_p.h>
#include <private/qquickitem_p.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qpainter.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglfunctions.h>
@@ -52,6 +54,8 @@ private slots:
void test_largeAnimation();
void test_reparenting();
void test_changeSourceToSmallerImgKeepingBigFrameSize();
+ void test_infiniteLoops();
+ void test_implicitSize();
};
void tst_qquickanimatedsprite::initTestCase()
@@ -62,11 +66,11 @@ void tst_qquickanimatedsprite::initTestCase()
void tst_qquickanimatedsprite::test_properties()
{
- QQuickView *window = new QQuickView(0);
+ QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("basic.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QVERIFY(window->rootObject());
QQuickAnimatedSprite* sprite = window->rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
@@ -77,21 +81,24 @@ void tst_qquickanimatedsprite::test_properties()
QVERIFY(sprite->interpolate());
QCOMPARE(sprite->loops(), 30);
+ QSignalSpy finishedSpy(sprite, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
sprite->setRunning(false);
QVERIFY(!sprite->running());
+ // The finished() signal shouldn't be emitted when running is manually set to false.
+ QCOMPARE(finishedSpy.count(), 0);
sprite->setInterpolate(false);
QVERIFY(!sprite->interpolate());
-
- delete window;
}
void tst_qquickanimatedsprite::test_runningChangedSignal()
{
- QQuickView *window = new QQuickView(0);
+ QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("runningChange.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QVERIFY(window->rootObject());
QQuickAnimatedSprite* sprite = window->rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
@@ -100,12 +107,15 @@ void tst_qquickanimatedsprite::test_runningChangedSignal()
QVERIFY(!sprite->running());
QSignalSpy runningChangedSpy(sprite, SIGNAL(runningChanged(bool)));
+ QSignalSpy finishedSpy(sprite, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
sprite->setRunning(true);
QTRY_COMPARE(runningChangedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
QTRY_VERIFY(!sprite->running());
QTRY_COMPARE(runningChangedSpy.count(), 2);
-
- delete window;
+ QCOMPARE(finishedSpy.count(), 1);
}
template <typename T>
@@ -117,7 +127,7 @@ static bool isWithinRange(T min, T value, T max)
void tst_qquickanimatedsprite::test_frameChangedSignal()
{
- QQuickView *window = new QQuickView(0);
+ QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("frameChange.qml"));
window->show();
@@ -126,7 +136,7 @@ void tst_qquickanimatedsprite::test_frameChangedSignal()
QQuickAnimatedSprite* sprite = window->rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
QSignalSpy frameChangedSpy(sprite, SIGNAL(currentFrameChanged(int)));
QVERIFY(sprite);
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QVERIFY(!sprite->running());
QVERIFY(!sprite->paused());
@@ -154,8 +164,6 @@ void tst_qquickanimatedsprite::test_frameChangedSignal()
prevFrame = frame;
}
QCOMPARE(loopCounter, 3);
-
- delete window;
}
void tst_qquickanimatedsprite::test_largeAnimation_data()
@@ -214,11 +222,11 @@ void tst_qquickanimatedsprite::test_largeAnimation()
{
QFETCH(bool, frameSync);
- QQuickView *window = new QQuickView(0);
+ QScopedPointer<QQuickView> window(new QQuickView);
window->engine()->addImageProvider(QLatin1String("test"), new AnimationImageProvider);
window->setSource(testFileUrl("largeAnimation.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QVERIFY(window->rootObject());
QQuickAnimatedSprite* sprite = window->rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
@@ -264,7 +272,6 @@ void tst_qquickanimatedsprite::test_largeAnimation()
maxTextureSize /= 512;
QVERIFY(maxFrame > maxTextureSize); // make sure we go beyond the texture width limitation
QCOMPARE(loopCounter, sprite->loops());
- delete window;
}
void tst_qquickanimatedsprite::test_reparenting()
@@ -279,20 +286,20 @@ void tst_qquickanimatedsprite::test_reparenting()
QVERIFY(sprite);
QTRY_VERIFY(sprite->running());
- sprite->setParentItem(0);
+ sprite->setParentItem(nullptr);
sprite->setParentItem(window.rootObject());
// don't crash (QTBUG-51162)
sprite->polish();
- QTRY_COMPARE(QQuickItemPrivate::get(sprite)->polishScheduled, true);
- QTRY_COMPARE(QQuickItemPrivate::get(sprite)->polishScheduled, false);
+ QVERIFY(QQuickTest::qIsPolishScheduled(sprite));
+ QVERIFY(QQuickTest::qWaitForItemPolished(sprite));
}
class KillerThread : public QThread
{
Q_OBJECT
protected:
- void run() Q_DECL_OVERRIDE {
+ void run() override {
sleep(3);
qFatal("Either the GUI or the render thread is stuck in an infinite loop.");
}
@@ -313,7 +320,7 @@ void tst_qquickanimatedsprite::test_changeSourceToSmallerImgKeepingBigFrameSize(
QQmlProperty big(sprite, "big");
big.write(QVariant::fromValue(false));
- KillerThread *killer = new KillerThread;
+ QScopedPointer<KillerThread> killer(new KillerThread);
killer->start(); // will kill us in case the GUI or render thread enters an infinite loop
QTest::qWait(50); // let it draw with the new source.
@@ -322,7 +329,66 @@ void tst_qquickanimatedsprite::test_changeSourceToSmallerImgKeepingBigFrameSize(
killer->terminate();
killer->wait();
- delete killer;
+}
+
+void tst_qquickanimatedsprite::test_implicitSize()
+{
+ QQuickView window;
+ window.setSource(testFileUrl("basic.qml"));
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject());
+
+ QQuickAnimatedSprite* sprite = window.rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
+ QVERIFY(sprite);
+ QCOMPARE(sprite->frameWidth(), 31);
+ QCOMPARE(sprite->frameHeight(), 30);
+ QCOMPARE(sprite->implicitWidth(), 31);
+ QCOMPARE(sprite->implicitHeight(), 30);
+
+ // Ensure that implicitWidth matches frameWidth.
+ QSignalSpy frameWidthChangedSpy(sprite, SIGNAL(frameWidthChanged(int)));
+ QVERIFY(frameWidthChangedSpy.isValid());
+
+ QSignalSpy frameImplicitWidthChangedSpy(sprite, SIGNAL(implicitWidthChanged()));
+ QVERIFY(frameImplicitWidthChangedSpy.isValid());
+
+ sprite->setFrameWidth(20);
+ QCOMPARE(frameWidthChangedSpy.count(), 1);
+ QCOMPARE(frameImplicitWidthChangedSpy.count(), 1);
+
+ // Ensure that implicitHeight matches frameHeight.
+ QSignalSpy frameHeightChangedSpy(sprite, SIGNAL(frameHeightChanged(int)));
+ QVERIFY(frameHeightChangedSpy.isValid());
+
+ QSignalSpy frameImplicitHeightChangedSpy(sprite, SIGNAL(implicitHeightChanged()));
+ QVERIFY(frameImplicitHeightChangedSpy.isValid());
+
+ sprite->setFrameHeight(20);
+ QCOMPARE(frameHeightChangedSpy.count(), 1);
+ QCOMPARE(frameImplicitHeightChangedSpy.count(), 1);
+}
+
+void tst_qquickanimatedsprite::test_infiniteLoops()
+{
+ QQuickView window;
+ window.setSource(testFileUrl("infiniteLoops.qml"));
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject());
+
+ QQuickAnimatedSprite* sprite = qobject_cast<QQuickAnimatedSprite*>(window.rootObject());
+ QVERIFY(sprite);
+
+ QTRY_VERIFY(sprite->running());
+
+ QSignalSpy finishedSpy(sprite, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ // The finished() signal shouldn't be emitted for infinite animations.
+ const int previousFrame = sprite->currentFrame();
+ QTRY_VERIFY(sprite->currentFrame() != previousFrame);
+ QCOMPARE(finishedSpy.count(), 0);
}
QTEST_MAIN(tst_qquickanimatedsprite)
diff --git a/tests/auto/quick/qquickanimations/BLACKLIST b/tests/auto/quick/qquickanimations/BLACKLIST
deleted file mode 100644
index e45c141d17..0000000000
--- a/tests/auto/quick/qquickanimations/BLACKLIST
+++ /dev/null
@@ -1,40 +0,0 @@
-# QTBUG-45466 QTBUG-29062
-[simpleProperty]
-osx-10.9 developer-build
-[badTypes]
-windows msvc-2010 32bit developer-build
-[mixedTypes]
-windows msvc-2010 32bit developer-build
-[properties]
-windows msvc-2010 32bit developer-build
-[propertiesTransition]
-windows msvc-2010 32bit developer-build
-[pathTransition]
-windows msvc-2010 32bit developer-build
-[disabledTransition]
-windows msvc-2010 32bit developer-build
-[rotation]
-windows msvc-2010 32bit developer-build
-[startStopSignals]
-windows msvc-2010 32bit developer-build
-[runningTrueBug]
-windows msvc-2010 32bit developer-build
-[nonTransitionBug]
-windows msvc-2010 32bit developer-build
-[registrationBug]
-windows msvc-2010 32bit developer-build
-[alwaysRunToEndRestartBug]
-windows msvc-2010 32bit developer-build
-[loopingBug]
-windows msvc-2010 32bit developer-build
-[pathAnimationInOutBackBug]
-windows msvc-2010 32bit developer-build
-[reparent]
-windows msvc-2012 64bit developer-build
-windows msvc-2010 32bit developer-build
-[simpleAnchor]
-windows msvc-2010 32bit developer-build
-[simplePath]
-windows gcc developer-build
-windows msvc-2010 32bit developer-build
-
diff --git a/tests/auto/quick/qquickanimations/data/finished.qml b/tests/auto/quick/qquickanimations/data/finished.qml
new file mode 100644
index 0000000000..a18b321501
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/finished.qml
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ width: 400
+ height: 400
+
+ property bool finishedUsableInQml: false
+
+ property alias simpleTopLevelAnimation: simpleTopLevelAnimation
+ property real foo: 0
+
+ property alias transitionRect: transitionRect
+ property alias transition: transition
+ property alias animationWithinTransition: animationWithinTransition
+
+ property real bar: 0
+ property alias animationWithinBehavior: animationWithinBehavior
+ property alias behavior: behavior
+
+ NumberAnimation {
+ id: simpleTopLevelAnimation
+ target: root
+ property: "foo"
+ from: 0
+ to: 1
+ duration: 10
+
+ onFinished: finishedUsableInQml = true
+ }
+
+ Rectangle {
+ id: transitionRect
+ color: "green"
+ width: 50
+ height: 50
+ anchors.centerIn: parent
+
+ states: State {
+ name: "go"
+ }
+ transitions: Transition {
+ id: transition
+ to: "go"
+ SequentialAnimation {
+ NumberAnimation {
+ id: animationWithinTransition
+ duration: 10
+ property: "foo"
+ from: 1
+ to: 2
+ }
+ }
+ }
+ }
+
+ Behavior on bar {
+ id: behavior
+ NumberAnimation {
+ id: animationWithinBehavior
+ duration: 10
+ property: "bar"
+ from: 0
+ to: 1
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/data/replacingTransitions.qml b/tests/auto/quick/qquickanimations/data/replacingTransitions.qml
new file mode 100644
index 0000000000..ff7c50cd67
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/replacingTransitions.qml
@@ -0,0 +1,51 @@
+import QtQuick 2.9
+
+Rectangle {
+ id: theRoot
+ property alias model: theModel
+ property alias addTimer: addToModel
+ property alias addTransition: addTrans
+ property alias displaceTransition: displaceTrans
+
+ width: 400
+ height: 400
+
+ ListModel {
+ id: theModel
+ }
+ Timer {
+ id: addToModel
+ interval: 1000
+ running: false
+ repeat: true
+ onTriggered: {
+ theModel.insert(0, {"name": "item " + theModel.count})
+ if (theModel.count > 2)
+ stop()
+ }
+ }
+ Component {
+ id: listDelegate
+ Text {
+ text: name
+ }
+ }
+ ListView {
+ id: listView
+
+ property int animationDuration: 10000
+
+ anchors.fill: parent
+ model: theModel
+ delegate: listDelegate
+ add: Transition {
+ id: addTrans
+ NumberAnimation { properties: "x"; from: 400; duration: listView.animationDuration }
+ NumberAnimation { properties: "y"; from: 400; duration: listView.animationDuration }
+ }
+ addDisplaced: Transition {
+ id: displaceTrans
+ NumberAnimation { properties: "x,y"; duration: listView.animationDuration }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index fbd6c9c97e..961506372a 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -29,12 +29,15 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/qquickview.h>
+#include <QtQml/private/qqmltimer_p.h>
+#include <QtQml/private/qqmllistmodel_p.h>
#include <QtQml/private/qanimationgroupjob_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/private/qquickitemanimation_p.h>
#include <QtQuick/private/qquickitemanimation_p_p.h>
#include <QtQuick/private/qquicktransition_p.h>
#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuick/private/qquickanimatorjob_p.h>
#include <QtQuick/private/qquickpathinterpolator_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QEasingCurve>
@@ -103,6 +106,9 @@ private slots:
void defaultPropertyWarning();
void pathSvgAnimation();
void pathLineUnspecifiedXYBug();
+ void unsetAnimatorProxyJobWindow();
+ void finished();
+ void replacingTransitions();
};
#define QTIMED_COMPARE(lhs, rhs) do { \
@@ -118,12 +124,16 @@ void tst_qquickanimations::simpleProperty()
{
QQuickRectangle rect;
QQuickPropertyAnimation animation;
+ QSignalSpy fromChangedSpy(&animation, &QQuickPropertyAnimation::fromChanged);
+ QSignalSpy toChangedSpy(&animation, &QQuickPropertyAnimation::toChanged);
animation.setTargetObject(&rect);
animation.setProperty("x");
animation.setTo(200);
QCOMPARE(animation.target(), &rect);
QCOMPARE(animation.property(), QLatin1String("x"));
QCOMPARE(animation.to().toReal(), 200.0);
+ QCOMPARE(fromChangedSpy.count(), 0);
+ QCOMPARE(toChangedSpy.count(), 1);
animation.start();
QVERIFY(animation.isRunning());
QTest::qWait(animation.duration());
@@ -137,18 +147,25 @@ void tst_qquickanimations::simpleProperty()
animation.setCurrentTime(125);
QCOMPARE(animation.currentTime(), 125);
QCOMPARE(rect.x(),100.0);
+ animation.setFrom(100);
+ QCOMPARE(fromChangedSpy.count(), 1);
+ QCOMPARE(toChangedSpy.count(), 1);
}
void tst_qquickanimations::simpleNumber()
{
QQuickRectangle rect;
QQuickNumberAnimation animation;
+ QSignalSpy fromChangedSpy(&animation, &QQuickNumberAnimation::fromChanged);
+ QSignalSpy toChangedSpy(&animation, &QQuickNumberAnimation::toChanged);
animation.setTargetObject(&rect);
animation.setProperty("x");
animation.setTo(200);
QCOMPARE(animation.target(), &rect);
QCOMPARE(animation.property(), QLatin1String("x"));
QCOMPARE(animation.to(), qreal(200));
+ QCOMPARE(fromChangedSpy.count(), 0);
+ QCOMPARE(toChangedSpy.count(), 1);
animation.start();
QVERIFY(animation.isRunning());
QTest::qWait(animation.duration());
@@ -162,18 +179,25 @@ void tst_qquickanimations::simpleNumber()
animation.setCurrentTime(125);
QCOMPARE(animation.currentTime(), 125);
QCOMPARE(rect.x(), qreal(100));
+ animation.setFrom(100);
+ QCOMPARE(fromChangedSpy.count(), 1);
+ QCOMPARE(toChangedSpy.count(), 1);
}
void tst_qquickanimations::simpleColor()
{
QQuickRectangle rect;
QQuickColorAnimation animation;
+ QSignalSpy fromChangedSpy(&animation, &QQuickColorAnimation::fromChanged);
+ QSignalSpy toChangedSpy(&animation, &QQuickColorAnimation::toChanged);
animation.setTargetObject(&rect);
animation.setProperty("color");
animation.setTo(QColor("red"));
QCOMPARE(animation.target(), &rect);
QCOMPARE(animation.property(), QLatin1String("color"));
QCOMPARE(animation.to(), QColor("red"));
+ QCOMPARE(fromChangedSpy.count(), 0);
+ QCOMPARE(toChangedSpy.count(), 1);
animation.start();
QVERIFY(animation.isRunning());
QTest::qWait(animation.duration());
@@ -191,6 +215,8 @@ void tst_qquickanimations::simpleColor()
rect.setColor(QColor("green"));
animation.setFrom(QColor("blue"));
QCOMPARE(animation.from(), QColor("blue"));
+ QCOMPARE(fromChangedSpy.count(), 1);
+ QCOMPARE(toChangedSpy.count(), 1);
animation.restart();
QCOMPARE(rect.color(), QColor("blue"));
QVERIFY(animation.isRunning());
@@ -202,6 +228,8 @@ void tst_qquickanimations::simpleRotation()
{
QQuickRectangle rect;
QQuickRotationAnimation animation;
+ QSignalSpy fromChangedSpy(&animation, &QQuickRotationAnimation::fromChanged);
+ QSignalSpy toChangedSpy(&animation, &QQuickRotationAnimation::toChanged);
animation.setTargetObject(&rect);
animation.setProperty("rotation");
animation.setTo(270);
@@ -209,6 +237,8 @@ void tst_qquickanimations::simpleRotation()
QCOMPARE(animation.property(), QLatin1String("rotation"));
QCOMPARE(animation.to(), qreal(270));
QCOMPARE(animation.direction(), QQuickRotationAnimation::Numerical);
+ QCOMPARE(fromChangedSpy.count(), 0);
+ QCOMPARE(toChangedSpy.count(), 1);
animation.start();
QVERIFY(animation.isRunning());
QTest::qWait(animation.duration());
@@ -222,6 +252,9 @@ void tst_qquickanimations::simpleRotation()
animation.setCurrentTime(125);
QCOMPARE(animation.currentTime(), 125);
QCOMPARE(rect.rotation(), qreal(135));
+ animation.setFrom(90);
+ QCOMPARE(fromChangedSpy.count(), 1);
+ QCOMPARE(toChangedSpy.count(), 1);
}
void tst_qquickanimations::simplePath()
@@ -731,7 +764,7 @@ void tst_qquickanimations::badTypes()
QQuickItemPrivate::get(rect)->setState("state1");
- QQuickRectangle *myRect = 0;
+ QQuickRectangle *myRect = nullptr;
QTRY_VERIFY(myRect = rect->findChild<QQuickRectangle*>("MyRect"));
QTRY_COMPARE(myRect->x(),qreal(200));
}
@@ -1124,7 +1157,7 @@ void tst_qquickanimations::easingProperties()
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
- QVERIFY(animObject != 0);
+ QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::InOutQuad);
}
@@ -1135,7 +1168,7 @@ void tst_qquickanimations::easingProperties()
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
- QVERIFY(animObject != 0);
+ QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::OutBounce);
QCOMPARE(animObject->easing().amplitude(), 5.0);
}
@@ -1147,7 +1180,7 @@ void tst_qquickanimations::easingProperties()
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
- QVERIFY(animObject != 0);
+ QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::OutElastic);
QCOMPARE(animObject->easing().amplitude(), 5.0);
QCOMPARE(animObject->easing().period(), 3.0);
@@ -1160,7 +1193,7 @@ void tst_qquickanimations::easingProperties()
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
- QVERIFY(animObject != 0);
+ QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::InOutBack);
QCOMPARE(animObject->easing().overshoot(), 2.0);
}
@@ -1172,9 +1205,9 @@ void tst_qquickanimations::easingProperties()
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
- QVERIFY(animObject != 0);
+ QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::BezierSpline);
- QList<QPointF> points = animObject->easing().cubicBezierSpline();
+ QVector<QPointF> points = animObject->easing().toCubicSpline();
QCOMPARE(points.count(), 3);
QCOMPARE(points.at(0), QPointF(0.5, 0.2));
QCOMPARE(points.at(1), QPointF(0.13, 0.65));
@@ -1295,7 +1328,7 @@ void tst_qquickanimations::nonTransitionBug()
QQmlComponent c(&engine, testFileUrl("nonTransitionBug.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
@@ -1321,7 +1354,7 @@ void tst_qquickanimations::registrationBug()
QQmlComponent c(&engine, testFileUrl("registrationBug.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QTRY_COMPARE(rect->property("value"), QVariant(int(100)));
}
@@ -1331,10 +1364,10 @@ void tst_qquickanimations::doubleRegistrationBug()
QQmlComponent c(&engine, testFileUrl("doubleRegistrationBug.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
- QVERIFY(anim != 0);
+ QVERIFY(anim != nullptr);
QTRY_COMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Stopped);
}
@@ -1372,7 +1405,7 @@ void tst_qquickanimations::transitionAssignmentBug()
QQmlComponent c(&engine, testFileUrl("transitionAssignmentBug.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->property("nullObject").toBool(), false);
}
@@ -1384,7 +1417,7 @@ void tst_qquickanimations::pauseBindingBug()
QQmlComponent c(&engine, testFileUrl("pauseBindingBug.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Paused);
@@ -1398,7 +1431,7 @@ void tst_qquickanimations::pauseBug()
QQmlComponent c(&engine, testFileUrl("pauseBug.qml"));
QQuickAbstractAnimation *anim = qobject_cast<QQuickAbstractAnimation*>(c.create());
- QVERIFY(anim != 0);
+ QVERIFY(anim != nullptr);
QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Paused);
QCOMPARE(anim->isPaused(), true);
QCOMPARE(anim->isRunning(), true);
@@ -1415,14 +1448,14 @@ void tst_qquickanimations::loopingBug()
QObject *obj = c.create();
QQuickAbstractAnimation *anim = obj->findChild<QQuickAbstractAnimation*>();
- QVERIFY(anim != 0);
+ QVERIFY(anim != nullptr);
QCOMPARE(anim->qtAnimation()->totalDuration(), 300);
QCOMPARE(anim->isRunning(), true);
QTRY_COMPARE(static_cast<QAnimationGroupJob*>(anim->qtAnimation())->firstChild()->currentLoop(), 2);
QTRY_COMPARE(anim->isRunning(), false);
QQuickRectangle *rect = obj->findChild<QQuickRectangle*>();
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->rotation(), qreal(90));
delete obj;
@@ -1567,6 +1600,129 @@ void tst_qquickanimations::pathLineUnspecifiedXYBug()
QCOMPARE(redRect->y(), qreal(0));
}
+void tst_qquickanimations::unsetAnimatorProxyJobWindow()
+{
+ QQuickWindow window;
+ QQuickItem item(window.contentItem());
+ QQuickAbstractAnimation animation(&item);
+ QAbstractAnimationJob *job = new QAbstractAnimationJob;
+ QQuickAnimatorProxyJob proxy(job, &animation);
+ QQuickItem dummy;
+ item.setParentItem(&dummy);
+ QSignalSpy spy(&window, SIGNAL(sceneGraphInitialized()));
+ window.show();
+ if (spy.count() < 1)
+ spy.wait();
+ QCOMPARE(proxy.job().data(), job);
+}
+
+void tst_qquickanimations::finished()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("finished.qml"));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(root);
+
+ // Test that finished() is emitted for a simple top-level animation.
+ // (Each test is in its own block so that we can reuse the nice signal names :))
+ {
+ QQuickAbstractAnimation *simpleTopLevelAnimation
+ = root->property("simpleTopLevelAnimation").value<QQuickAbstractAnimation*>();
+ QVERIFY(simpleTopLevelAnimation);
+
+ QSignalSpy stoppedSpy(simpleTopLevelAnimation, SIGNAL(stopped()));
+ QVERIFY(stoppedSpy.isValid());
+
+ QSignalSpy finishedSpy(simpleTopLevelAnimation, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ QVERIFY(simpleTopLevelAnimation->setProperty("running", QVariant(true)));
+ QTRY_COMPARE(stoppedSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 1);
+
+ // Test that the signal is properly revisioned and hence accessible from QML.
+ QCOMPARE(root->property("finishedUsableInQml").toBool(), true);
+ }
+
+ // Test that finished() is not emitted for animations within a Transition.
+ {
+ QObject *transition = root->property("transition").value<QObject*>();
+ QVERIFY(transition);
+
+ QSignalSpy runningChangedSpy(transition, SIGNAL(runningChanged()));
+ QVERIFY(runningChangedSpy.isValid());
+
+ QQuickAbstractAnimation *animationWithinTransition
+ = root->property("animationWithinTransition").value<QQuickAbstractAnimation*>();
+ QVERIFY(animationWithinTransition);
+
+ QSignalSpy stoppedSpy(animationWithinTransition, SIGNAL(stopped()));
+ QVERIFY(stoppedSpy.isValid());
+
+ QSignalSpy finishedSpy(animationWithinTransition, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ QObject *transitionRect = root->property("transitionRect").value<QObject*>();
+ QVERIFY(transitionRect);
+ QVERIFY(transitionRect->setProperty("state", QVariant(QLatin1String("go"))));
+ QTRY_COMPARE(runningChangedSpy.count(), 1);
+ QCOMPARE(stoppedSpy.count(), 0);
+ QCOMPARE(finishedSpy.count(), 0);
+ }
+
+ // Test that finished() is not emitted for animations within a Behavior.
+ {
+ QQuickAbstractAnimation *animationWithinBehavior
+ = root->property("animationWithinBehavior").value<QQuickAbstractAnimation*>();
+ QVERIFY(animationWithinBehavior);
+
+ QSignalSpy stoppedSpy(animationWithinBehavior, SIGNAL(stopped()));
+ QVERIFY(stoppedSpy.isValid());
+
+ QSignalSpy finishedSpy(animationWithinBehavior, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+
+ QVERIFY(root->setProperty("bar", QVariant(1.0)));
+ QTRY_COMPARE(root->property("bar").toReal(), 1.0);
+ QCOMPARE(stoppedSpy.count(), 0);
+ QCOMPARE(finishedSpy.count(), 0);
+ }
+}
+
+void tst_qquickanimations::replacingTransitions()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("replacingTransitions.qml"));
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));
+ if (!c.errors().isEmpty())
+ qDebug() << c.errorString();
+ QVERIFY(rect);
+
+ QQmlTimer *addTimer = rect->property("addTimer").value<QQmlTimer*>();
+ QVERIFY(addTimer);
+ QCOMPARE(addTimer->isRunning(), false);
+
+ QQuickTransition *addTrans = rect->property("addTransition").value<QQuickTransition*>();
+ QVERIFY(addTrans);
+ QCOMPARE(addTrans->running(), false);
+
+ QQuickTransition *displaceTrans = rect->property("displaceTransition").value<QQuickTransition*>();
+ QVERIFY(displaceTrans);
+ QCOMPARE(displaceTrans->running(), false);
+
+ QQmlListModel *model = rect->property("model").value<QQmlListModel *>();
+ QVERIFY(model);
+ QCOMPARE(model->count(), 0);
+
+ addTimer->start();
+ QTest::qWait(1000 + 1000 + 10000);
+
+ QTRY_COMPARE(addTimer->isRunning(), false);
+ QTRY_COMPARE(addTrans->running(), false);
+ QTRY_COMPARE(displaceTrans->running(), false);
+ QCOMPARE(model->count(), 3);
+}
+
QTEST_MAIN(tst_qquickanimations)
#include "tst_qquickanimations.moc"
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index e428a1fc6e..3526eb98be 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -67,7 +67,7 @@ void tst_qquickapplication::cleanup()
{
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
- QTest::waitForEvents();
+ QCoreApplication::processEvents();
}
}
@@ -88,31 +88,37 @@ void tst_qquickapplication::active()
QQuickWindow window;
item->setParentItem(window.contentItem());
- // not active
- QVERIFY(!item->property("active").toBool());
- QVERIFY(!item->property("active2").toBool());
-
- // active
- window.show();
- window.requestActivate();
- QTest::qWaitForWindowActive(&window);
- QCOMPARE(QGuiApplication::focusWindow(), &window);
- QVERIFY(item->property("active").toBool());
- QVERIFY(item->property("active2").toBool());
-
- QWindowSystemInterface::handleWindowActivated(0);
-
-#ifdef Q_OS_OSX
- // OS X has the concept of "reactivation"
- QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
- QVERIFY(item->property("active").toBool());
- QVERIFY(item->property("active2").toBool());
-#else
- // not active again
- QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
- QVERIFY(!item->property("active").toBool());
- QVERIFY(!item->property("active2").toBool());
-#endif
+ // If the platform plugin has the ApplicationState capability, app activation originate from it
+ // as a result of a system event. We therefore have to simulate these events here.
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
+
+ // Flush pending events, in case the platform have already queued real application state events
+ QWindowSystemInterface::flushWindowSystemEvents();
+
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
+ QWindowSystemInterface::flushWindowSystemEvents();
+ QVERIFY(item->property("active").toBool());
+ QVERIFY(item->property("active2").toBool());
+
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
+ QWindowSystemInterface::flushWindowSystemEvents();
+ QVERIFY(!item->property("active").toBool());
+ QVERIFY(!item->property("active2").toBool());
+ } else {
+ // Otherwise, app activation is triggered by window activation.
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QCOMPARE(QGuiApplication::focusWindow(), &window);
+ QVERIFY(item->property("active").toBool());
+ QVERIFY(item->property("active2").toBool());
+
+ // not active again
+ QWindowSystemInterface::handleWindowActivated(nullptr);
+ QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
+ QVERIFY(!item->property("active").toBool());
+ QVERIFY(!item->property("active2").toBool());
+ }
}
void tst_qquickapplication::state()
@@ -165,13 +171,13 @@ void tst_qquickapplication::state()
// triggered by window activation.
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(QGuiApplication::focusWindow(), &window);
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationActive);
// not active again
- QWindowSystemInterface::handleWindowActivated(0);
+ QWindowSystemInterface::handleWindowActivated(nullptr);
QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive);
QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive);
diff --git a/tests/auto/quick/qquickbehaviors/BLACKLIST b/tests/auto/quick/qquickbehaviors/BLACKLIST
deleted file mode 100644
index 9be4da176d..0000000000
--- a/tests/auto/quick/qquickbehaviors/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[currentValue]
-windows
diff --git a/tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml b/tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml
new file mode 100644
index 0000000000..0ac7f87c42
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.4
+
+Item {
+ id: root
+
+ property bool someValue
+ Behavior on someValue {
+ objectName: "behavior"
+ ScriptAction { script: { parent.behaviorTriggered = true }}
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/data/aliased.qml b/tests/auto/quick/qquickbehaviors/data/aliased.qml
index e65e035d83..1840cdd22e 100644
--- a/tests/auto/quick/qquickbehaviors/data/aliased.qml
+++ b/tests/auto/quick/qquickbehaviors/data/aliased.qml
@@ -17,6 +17,7 @@ Rectangle {
anchors.fill: parent
value: accelerating ? 400 : 0
Behavior on value {
+ objectName: "behavior"
NumberAnimation {
duration: 500
}
diff --git a/tests/auto/quick/qquickbehaviors/data/oneway.qml b/tests/auto/quick/qquickbehaviors/data/oneway.qml
new file mode 100644
index 0000000000..0b438b80f6
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/oneway.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.0
+Rectangle {
+ width: 400
+ height: 400
+ Rectangle {
+ id: rect
+ objectName: "MyRectOneWay"
+ width: 100; height: 100; color: "green"
+ Behavior on x {
+ id: behavior
+ objectName: "MyBehaviorOneWay";
+ enabled: (behavior.targetValue === 0)
+ NumberAnimation {
+ id: ani
+ objectName: "MyAnimationOneWay";
+ duration: 200;
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/data/overwrittenbehavior.qml b/tests/auto/quick/qquickbehaviors/data/overwrittenbehavior.qml
new file mode 100644
index 0000000000..e627c45782
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/overwrittenbehavior.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.4
+
+Item {
+ property bool behaviorTriggered
+ property bool someProperty
+
+ ItemWithInnerBehavior {
+ //the existence of this property triggers the bug
+ property bool iDoAbsolutelyNothing
+
+ Component.onCompleted: parent.someProperty = true
+ someValue: parent.someProperty
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml b/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml
index d2da8d1b27..f87febf958 100644
--- a/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml
+++ b/tests/auto/quick/qquickbehaviors/data/qtbug21549-2.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquickbehaviors/qquickbehaviors.pro b/tests/auto/quick/qquickbehaviors/qquickbehaviors.pro
index 51bc42c390..fd64eb1d40 100644
--- a/tests/auto/quick/qquickbehaviors/qquickbehaviors.pro
+++ b/tests/auto/quick/qquickbehaviors/qquickbehaviors.pro
@@ -7,5 +7,5 @@ include (../../shared/util.pri)
macx:CONFIG -= app_bundle
TESTDATA = data/*
-
+DISTFILES = $$files(data/*)
QT += core-private gui-private qml-private quick-private testlib
diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
index 80c76a377b..6367f327da 100644
--- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
+++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
@@ -72,6 +72,8 @@ private slots:
void currentValue();
void disabledWriteWhileRunning();
void aliasedProperty();
+ void innerBehaviorOverwritten();
+ void oneWay();
};
void tst_qquickbehaviors::simpleBehavior()
@@ -392,7 +394,7 @@ void tst_qquickbehaviors::delayedRegistration()
QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickItem *innerRect = rect->property("myItem").value<QQuickItem*>();
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QCOMPARE(innerRect->property("x").toInt(), int(0));
@@ -409,7 +411,7 @@ void tst_qquickbehaviors::startOnCompleted()
QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickItem *innerRect = rect->findChild<QQuickRectangle*>();
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QCOMPARE(innerRect->property("x").toInt(), int(0));
@@ -426,7 +428,7 @@ void tst_qquickbehaviors::multipleChangesToValueType()
QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
QQuickText *text = rect->findChild<QQuickText *>();
- QVERIFY(text != 0);
+ QVERIFY(text != nullptr);
QFont value;
value.setPointSize(24);
@@ -515,6 +517,7 @@ void tst_qquickbehaviors::disabledWriteWhileRunning()
myRect->setProperty("x", 200);
QCOMPARE(myAnimation->isRunning(), true);
QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200));
+ QCOMPARE(myBehavior->targetValue(), 200); // grabbed before starting the animation
// set disabled while animation is in progress
myBehavior->setProperty("enabled", false);
@@ -525,6 +528,7 @@ void tst_qquickbehaviors::disabledWriteWhileRunning()
myRect->setProperty("x", 100);
QCOMPARE(myAnimation->isRunning(), false);
QCOMPARE(myRect->x(), qreal(100));
+ QCOMPARE(myBehavior->targetValue(), 100);
QTest::qWait(200);
QCOMPARE(myRect->x(), qreal(100));
}
@@ -545,17 +549,20 @@ void tst_qquickbehaviors::disabledWriteWhileRunning()
// initial values
QCOMPARE(myBehavior->enabled(), true);
+ QCOMPARE(myBehavior->targetValue(), QVariant());
QCOMPARE(myAnimation->isRunning(), false);
QCOMPARE(myRect->x(), qreal(0));
// start animation
myRect->setProperty("x", 200);
QCOMPARE(myAnimation->isRunning(), true);
+ QCOMPARE(myBehavior->targetValue(), 200);
QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200));
//set second value
myRect->setProperty("x", 300);
QCOMPARE(myAnimation->isRunning(), true);
+ QCOMPARE(myBehavior->targetValue(), 300);
QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200));
// set disabled while animation is in progress
@@ -567,6 +574,7 @@ void tst_qquickbehaviors::disabledWriteWhileRunning()
myRect->setProperty("x", 100);
QCOMPARE(myAnimation->isRunning(), false);
QCOMPARE(myRect->x(), qreal(100));
+ QCOMPARE(myBehavior->targetValue(), 100);
QTest::qWait(200);
QCOMPARE(myRect->x(), qreal(100));
}
@@ -579,7 +587,12 @@ void tst_qquickbehaviors::aliasedProperty()
QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));
QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
+ QQuickBehavior* behavior =
+ qobject_cast<QQuickBehavior*>(rect->findChild<QQuickBehavior*>("behavior"));
+ QSignalSpy targetValueSpy(behavior, SIGNAL(targetValueChanged()));
QQuickItemPrivate::get(rect.data())->setState("moved");
+ QCOMPARE(behavior->targetValue(), 400);
+ QCOMPARE(targetValueSpy.count(), 1);
QScopedPointer<QQuickRectangle> acc(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("acc")));
QScopedPointer<QQuickRectangle> range(qobject_cast<QQuickRectangle*>(acc->findChild<QQuickRectangle*>("range")));
QTRY_VERIFY(acc->property("value").toDouble() > 0);
@@ -589,6 +602,51 @@ void tst_qquickbehaviors::aliasedProperty()
//i.e. the behavior has been triggered
}
+void tst_qquickbehaviors::innerBehaviorOverwritten()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("overwrittenbehavior.qml"));
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(c.create()));
+ QQuickBehavior* behavior =
+ qobject_cast<QQuickBehavior*>(item->findChild<QQuickBehavior*>("behavior"));
+ QVERIFY(item->property("behaviorTriggered").toBool());
+ QCOMPARE(behavior->targetValue(), true);
+}
+
+void tst_qquickbehaviors::oneWay()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("oneway.qml"));
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
+ QQuickBehavior* behavior =
+ qobject_cast<QQuickBehavior*>(rect->findChild<QQuickBehavior*>("MyBehaviorOneWay"));
+ QCOMPARE(behavior->enabled(), false);
+ QCOMPARE(behavior->targetValue(), QVariant());
+
+ QSignalSpy targetValueSpy(behavior, SIGNAL(targetValueChanged()));
+ QQuickRectangle *myRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRectOneWay"));
+ myRect->setProperty("x", 100);
+ QCOMPARE(behavior->targetValue(), 100);
+ QCOMPARE(targetValueSpy.count(), 1);
+ QCOMPARE(behavior->enabled(), false);
+ qreal x = myRect->x();
+ QCOMPARE(x, qreal(100)); //should change immediately
+ QQuickNumberAnimation *myAnimation =
+ qobject_cast<QQuickNumberAnimation*>(behavior->findChild<QQuickNumberAnimation*>("MyAnimationOneWay"));
+ QCOMPARE(myAnimation->isRunning(), false);
+
+ myRect->setProperty("x", 0);
+ QCOMPARE(behavior->targetValue(), 0);
+ QCOMPARE(targetValueSpy.count(), 2);
+ QCOMPARE(behavior->enabled(), true);
+ QCOMPARE(myAnimation->isRunning(), true);
+ QVERIFY(myRect->x() > 0.0);
+ QTRY_VERIFY(myRect->x() < 100.0);
+ QTRY_COMPARE(myRect->x(), qreal(0));
+ QCOMPARE(myAnimation->isRunning(), false);
+}
+
QTEST_MAIN(tst_qquickbehaviors)
#include "tst_qquickbehaviors.moc"
diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
index 71b0160c8e..9292e1886a 100644
--- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
+++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
@@ -101,7 +101,7 @@ void tst_qquickborderimage::noSource()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->source(), QUrl());
QCOMPARE(obj->width(), 0.);
QCOMPARE(obj->height(), 0.);
@@ -153,7 +153,7 @@ void tst_qquickborderimage::imageSource()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
if (remote)
QTRY_COMPARE(obj->status(), QQuickBorderImage::Loading);
@@ -183,7 +183,7 @@ void tst_qquickborderimage::clearSource()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickBorderImage::Ready);
QCOMPARE(obj->width(), 120.);
QCOMPARE(obj->height(), 120.);
@@ -203,7 +203,7 @@ void tst_qquickborderimage::resized()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 300.);
QCOMPARE(obj->height(), 300.);
QCOMPARE(obj->sourceSize().width(), 120);
@@ -220,7 +220,7 @@ void tst_qquickborderimage::smooth()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 300.);
QCOMPARE(obj->height(), 300.);
QCOMPARE(obj->smooth(), true);
@@ -235,7 +235,7 @@ void tst_qquickborderimage::mirror()
QQuickView *window = new QQuickView;
window->setSource(testFileUrl("mirror.qml"));
QQuickBorderImage *image = qobject_cast<QQuickBorderImage*>(window->rootObject());
- QVERIFY(image != 0);
+ QVERIFY(image != nullptr);
QImage screenshot = window->grabWindow();
@@ -248,7 +248,7 @@ void tst_qquickborderimage::mirror()
screenshot = window->grabWindow();
window->show();
- QTest::qWaitForWindowExposed(window);
+ QVERIFY(QTest::qWaitForWindowExposed(window));
if (window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
QSKIP("QTBUG-53823");
QCOMPARE(screenshot, srcPixmap);
@@ -263,7 +263,7 @@ void tst_qquickborderimage::tileModes()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 100.);
QCOMPARE(obj->height(), 300.);
QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Repeat);
@@ -276,7 +276,7 @@ void tst_qquickborderimage::tileModes()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 300.);
QCOMPARE(obj->height(), 150.);
QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Round);
@@ -304,7 +304,7 @@ void tst_qquickborderimage::sciSource()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
if (remote)
QTRY_COMPARE(obj->status(), QQuickBorderImage::Loading);
@@ -352,7 +352,7 @@ void tst_qquickborderimage::invalidSciFile()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 300.);
QCOMPARE(obj->height(), 300.);
QCOMPARE(obj->status(), QQuickImageBase::Error);
@@ -380,7 +380,7 @@ void tst_qquickborderimage::validSciFiles()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 300.);
QCOMPARE(obj->height(), 300.);
QCOMPARE(obj->horizontalTileMode(), QQuickBorderImage::Round);
@@ -397,7 +397,7 @@ void tst_qquickborderimage::pendingRemoteRequest()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickBorderImage::Loading);
// verify no crash
@@ -450,7 +450,7 @@ void tst_qquickborderimage::statusChanges()
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
qRegisterMetaType<QQuickImageBase::Status>();
QSignalSpy spy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
obj->setSource(source);
if (remote)
server.sendDelayedItem();
@@ -473,7 +473,7 @@ void tst_qquickborderimage::sourceSizeChanges()
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("srcImage", "");
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged()));
@@ -539,7 +539,7 @@ void tst_qquickborderimage::progressAndStatusChanges()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickBorderImage *obj = qobject_cast<QQuickBorderImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickBorderImage::Ready);
QTRY_COMPARE(obj->progress(), 1.0);
@@ -590,13 +590,15 @@ void tst_qquickborderimage::borderImageMesh()
window->setSource(testFileUrl("nonmesh.qml"));
window->show();
- QTest::qWaitForWindowExposed(window);
+ QVERIFY(QTest::qWaitForWindowExposed(window));
QImage nonmesh = window->grabWindow();
window->setSource(testFileUrl("mesh.qml"));
QImage mesh = window->grabWindow();
- QVERIFY(QQuickVisualTestUtil::compareImages(mesh, nonmesh));
+ QString errorMessage;
+ QVERIFY2(QQuickVisualTestUtil::compareImages(mesh, nonmesh, &errorMessage),
+ qPrintable(errorMessage));
}
#endif
QTEST_MAIN(tst_qquickborderimage)
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
index 565f906fb1..8238d87313 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
@@ -151,9 +151,11 @@ CanvasTestCase {
{mimeType:"image/bmp"},
{mimeType:"image/jpeg"},
{mimeType:"image/x-portable-pixmap"},
- //{mimeType:"image/tiff"}, QTBUG-23980
{mimeType:"image/xpm"},
];
+ if (hasImageFormats)
+ imageTypes.push({ mimeType: "image/tiff" });
+
for (var i = 0; i < imageTypes.length; i++) {
ctx.fillStyle = "red";
ctx.fillRect(0, 0, c.width, c.height);
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml b/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml
index 00a12f2edc..7c87d896fb 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml
@@ -33,7 +33,7 @@ CanvasTestCase {
//comparePixel(ctx, 75,25, 63,63,191,255,3);
ctx.reset();
- var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g = ctx.createLinearGradient(0, 0, 100, 0);
g.addColorStop(0, '#ff0');
g.addColorStop(1, '#00f');
ctx.fillStyle = g;
@@ -44,7 +44,7 @@ CanvasTestCase {
ctx.reset();
- var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g = ctx.createLinearGradient(0, 0, 100, 0);
g.addColorStop(0, 'rgba(255,255,0, 0)');
g.addColorStop(1, 'rgba(0,0,255, 1)');
ctx.fillStyle = g;
@@ -55,7 +55,7 @@ CanvasTestCase {
ctx.reset();
canvas.width = 200;
- var g = ctx.createLinearGradient(0, 0, 200, 0);
+ g = ctx.createLinearGradient(0, 0, 200, 0);
g.addColorStop(0, '#ff0');
g.addColorStop(0.5, '#0ff');
g.addColorStop(1, '#f0f');
@@ -69,7 +69,7 @@ CanvasTestCase {
ctx.fillStyle = '#f00';
ctx.fillRect(0, 0, 100, 50);
- var g = ctx.createLinearGradient(25, 0, 75, 0);
+ g = ctx.createLinearGradient(25, 0, 75, 0);
g.addColorStop(0.4, '#0f0');
g.addColorStop(0.6, '#0f0');
@@ -82,7 +82,7 @@ CanvasTestCase {
ctx.reset();
ctx.canvas.width = 200;
- var g = ctx.createLinearGradient(0, 0, 200, 0);
+ g = ctx.createLinearGradient(0, 0, 200, 0);
g.addColorStop(0, '#f00');
g.addColorStop(0, '#ff0');
g.addColorStop(0.25, '#00f');
@@ -110,7 +110,7 @@ CanvasTestCase {
ctx.canvas.width = 100;
ctx.reset();
- var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g = ctx.createLinearGradient(0, 0, 100, 0);
var ps = [ 0, 1/10, 1/4, 1/3, 1/2, 3/4, 1 ];
for (var p = 0; p < ps.length; ++p)
{
@@ -129,7 +129,7 @@ CanvasTestCase {
ctx.reset();
- var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g = ctx.createLinearGradient(0, 0, 100, 0);
g.addColorStop(0, '#0f0');
g.addColorStop(1, '#0f0');
ctx.fillStyle = g;
@@ -139,7 +139,7 @@ CanvasTestCase {
ctx.reset();
- var g = ctx.createLinearGradient(0, 0, 0, 50);
+ g = ctx.createLinearGradient(0, 0, 0, 50);
g.addColorStop(0, '#ff0');
g.addColorStop(1, '#00f');
ctx.fillStyle = g;
@@ -154,7 +154,7 @@ CanvasTestCase {
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
- var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+ g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
g.addColorStop(0, '#f00');
g.addColorStop(1, '#f00');
ctx.fillStyle = g;
@@ -278,7 +278,7 @@ CanvasTestCase {
//comparePixel(ctx, 98,48, 0,255,0,255);
ctx.reset();
- var tol = 1; // tolerance to avoid antialiasing artifacts
+ tol = 1; // tolerance to avoid antialiasing artifacts
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
@@ -410,243 +410,243 @@ CanvasTestCase {
ctx.reset();
try { var err = false;
ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1);
- } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1);
- } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1)"); }
+ } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1)"); }
ctx.reset();
- try { var err = false;
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, 1, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(-Infinity, 0, 1, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(-Infinity, 0, 1, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(-Infinity, 0, 1, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(NaN, 0, 1, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(NaN, 0, 1, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(NaN, 0, 1, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, 1, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, -Infinity, 1, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, -Infinity, 1, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, -Infinity, 1, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, NaN, 1, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, NaN, 1, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, NaN, 1, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, Infinity, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, NaN, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, NaN, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, NaN, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, -Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, -Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, -Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, NaN, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, NaN, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, NaN, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, 0, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, 0, -Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, -Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, -Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, 0, NaN, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, NaN, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, NaN, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, 0, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, 0, 0, -Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, -Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, -Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, 0, 0, NaN);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, NaN)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, NaN)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(Infinity, 0, 1, 0, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, Infinity, 1, 0, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, Infinity, 0, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, 1);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, 1)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, 1)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, Infinity, 0, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, 0, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, 0, Infinity)"); }
+ try { err = false;
ctx.createRadialGradient(0, 0, 1, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, Infinity, Infinity)"); }
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, Infinity, Infinity)"); }
ctx.reset();
@@ -792,73 +792,73 @@ CanvasTestCase {
ctx.reset();
try { var err = false;
ctx.createLinearGradient(Infinity, 0, 1, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, 1, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, 1, 0)"); }
+ try { err = false;
ctx.createLinearGradient(-Infinity, 0, 1, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(-Infinity, 0, 1, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(-Infinity, 0, 1, 0)"); }
+ try { err = false;
ctx.createLinearGradient(NaN, 0, 1, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(NaN, 0, 1, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(NaN, 0, 1, 0)"); }
+ try { err = false;
ctx.createLinearGradient(0, Infinity, 1, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, 1, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, 1, 0)"); }
+ try { err = false;
ctx.createLinearGradient(0, -Infinity, 1, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, -Infinity, 1, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, -Infinity, 1, 0)"); }
+ try { err = false;
ctx.createLinearGradient(0, NaN, 1, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, NaN, 1, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, NaN, 1, 0)"); }
+ try { err = false;
ctx.createLinearGradient(0, 0, Infinity, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, Infinity, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, Infinity, 0)"); }
+ try { err = false;
ctx.createLinearGradient(0, 0, -Infinity, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, -Infinity, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, -Infinity, 0)"); }
+ try { err = false;
ctx.createLinearGradient(0, 0, NaN, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, NaN, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, NaN, 0)"); }
+ try { err = false;
ctx.createLinearGradient(0, 0, 1, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, Infinity)"); }
+ try { err = false;
ctx.createLinearGradient(0, 0, 1, -Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, -Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, -Infinity)"); }
+ try { err = false;
ctx.createLinearGradient(0, 0, 1, NaN);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, NaN)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, NaN)"); }
+ try { err = false;
ctx.createLinearGradient(Infinity, Infinity, 1, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, 1, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, 1, 0)"); }
+ try { err = false;
ctx.createLinearGradient(Infinity, Infinity, Infinity, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, Infinity, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, Infinity, 0)"); }
+ try { err = false;
ctx.createLinearGradient(Infinity, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createLinearGradient(Infinity, Infinity, 1, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, 1, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, 1, Infinity)"); }
+ try { err = false;
ctx.createLinearGradient(Infinity, 0, Infinity, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, Infinity, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, Infinity, 0)"); }
+ try { err = false;
ctx.createLinearGradient(Infinity, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, Infinity, Infinity)"); }
+ try { err = false;
ctx.createLinearGradient(Infinity, 0, 1, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, 1, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, 1, Infinity)"); }
+ try { err = false;
ctx.createLinearGradient(0, Infinity, Infinity, 0);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, Infinity, 0)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, Infinity, 0)"); }
+ try { err = false;
ctx.createLinearGradient(0, Infinity, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, Infinity, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, Infinity, Infinity)"); }
+ try { err = false;
ctx.createLinearGradient(0, Infinity, 1, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, 1, Infinity)"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, 1, Infinity)"); }
+ try { err = false;
ctx.createLinearGradient(0, 0, Infinity, Infinity);
- } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, Infinity, Infinity)"); }
+ } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, Infinity, Infinity)"); }
ctx.reset();
var g = ctx.createLinearGradient(0, 0, 200, 0);
@@ -918,29 +918,29 @@ CanvasTestCase {
var g = ctx.createLinearGradient(0, 0, 100, 0);
try { var err = false;
g.addColorStop(0, "");
- } catch (e) { if (e.code != DOMException.SYNTAX_ERR) fail("Failed assertion: expected exception of type SYNTAX_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type SYNTAX_ERR: g.addColorStop(0, \"\")"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.SYNTAX_ERR) fail("Failed assertion: expected exception of type SYNTAX_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type SYNTAX_ERR: g.addColorStop(0, \"\")"); }
+ try { err = false;
g.addColorStop(0, 'undefined');
- } catch (e) { if (e.code != DOMException.SYNTAX_ERR) fail("Failed assertion: expected exception of type SYNTAX_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type SYNTAX_ERR: g.addColorStop(0, 'undefined')"); }
+ } catch (e) { if (e.code !== DOMException.SYNTAX_ERR) fail("Failed assertion: expected exception of type SYNTAX_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type SYNTAX_ERR: g.addColorStop(0, 'undefined')"); }
ctx.reset();
g = ctx.createLinearGradient(0, 0, 100, 0);
- try { var err = false;
+ try { err = false;
g.addColorStop(-1, '#000');
- } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(-1, '#000')"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(-1, '#000')"); }
+ try { err = false;
g.addColorStop(2, '#000');
- } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(2, '#000')"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(2, '#000')"); }
+ try { err = false;
g.addColorStop(Infinity, '#000');
- } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(Infinity, '#000')"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(Infinity, '#000')"); }
+ try { err = false;
g.addColorStop(-Infinity, '#000');
- } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(-Infinity, '#000')"); }
- try { var err = false;
+ } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(-Infinity, '#000')"); }
+ try { err = false;
g.addColorStop(NaN, '#000');
- } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(NaN, '#000')"); }
+ } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(NaN, '#000')"); }
ctx.reset();
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml
index 7095602ea2..76b99a765e 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml
@@ -6,6 +6,10 @@ CanvasTestCase {
name: "imagedata"
function init_data() { return testData("2d"); }
function test_rounding(row) {
+ if ((Qt.platform.pluginName === "offscreen")
+ || (Qt.platform.pluginName === "minimal"))
+ skip("ctx.getImageData crashes on offscreen/minimal platforms");
+
var canvas = createCanvasObject(row);
var ctx = canvas.getContext('2d');
var size = 17
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml b/tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml
new file mode 100644
index 0000000000..dd14aef433
--- /dev/null
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_invalidContext.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+import QtTest 1.1
+
+Item {
+ id: root
+ width: 500
+ height: 500
+
+ Timer {
+ id: timer
+ interval: 1
+ running: true
+ repeat: true
+ onTriggered: {
+ if (myCanvas.parent == root) {
+ myCanvas.parent = null
+ } else {
+ myCanvas.parent = root
+ }
+ }
+ }
+
+ Canvas {
+ id: myCanvas
+ anchors.fill: parent
+ property var paintContext: null
+
+ function paint() {
+ paintContext.fillStyle = Qt.rgba(1, 0, 0, 1);
+ paintContext.fillRect(0, 0, width, height);
+ requestAnimationFrame(paint);
+ }
+
+ onAvailableChanged: {
+ if (available) {
+ paintContext = getContext("2d")
+ requestAnimationFrame(paint);
+ }
+ }
+ }
+
+ TestCase {
+ name: "invalidContext"
+ when: myCanvas.parent === null && myCanvas.paintContext !== null
+
+ function test_paintContextInvalid() {
+ verify(myCanvas.paintContext);
+ var caught = false;
+ try {
+ console.log(myCanvas.paintContext.fillStyle);
+ } catch(e) {
+ caught = true;
+ }
+ verify(caught);
+ timer.running = false
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_line.qml b/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
index 750f37638d..dc960a24d0 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_line.qml
@@ -834,5 +834,96 @@ CanvasTestCase {
ctx.lineCap = 'square';
compare(ctx.lineCap, 'square');
+ }
+
+ function test_lineDash(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+ ctx.reset();
+ ctx.strokeStyle = "#fff";
+ ctx.lineWidth = 2;
+ var pattern = [2, 3, 5, 1, 6, 3]
+ ctx.setLineDash(pattern)
+
+ compare(ctx.getLineDash(), pattern);
+
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(40, 0);
+ ctx.stroke();
+
+ comparePixel(ctx, 0,0, 255,255,255,255);
+ comparePixel(ctx, 1,0, 255,255,255,255);
+ comparePixel(ctx, 2,0, 255,255,255,255);
+ comparePixel(ctx, 3,0, 255,255,255,255);
+ comparePixel(ctx, 4,0, 0,0,0,0);
+ comparePixel(ctx, 5,0, 0,0,0,0);
+ comparePixel(ctx, 6,0, 0,0,0,0);
+ comparePixel(ctx, 7,0, 0,0,0,0);
+ comparePixel(ctx, 8,0, 0,0,0,0);
+ comparePixel(ctx, 9,0, 0,0,0,0);
+ comparePixel(ctx, 10,0, 255,255,255,255);
+ comparePixel(ctx, 11,0, 255,255,255,255);
+ comparePixel(ctx, 12,0, 255,255,255,255);
+ comparePixel(ctx, 13,0, 255,255,255,255);
+ comparePixel(ctx, 14,0, 255,255,255,255);
+ comparePixel(ctx, 15,0, 255,255,255,255);
+ comparePixel(ctx, 16,0, 255,255,255,255);
+ comparePixel(ctx, 17,0, 255,255,255,255);
+ comparePixel(ctx, 18,0, 255,255,255,255);
+ comparePixel(ctx, 19,0, 255,255,255,255);
+ comparePixel(ctx, 20,0, 0,0,0,0);
+ comparePixel(ctx, 21,0, 0,0,0,0);
+ comparePixel(ctx, 22,0, 255,255,255,255);
+ comparePixel(ctx, 23,0, 255,255,255,255);
+ comparePixel(ctx, 24,0, 255,255,255,255);
+ comparePixel(ctx, 25,0, 255,255,255,255);
+ comparePixel(ctx, 26,0, 255,255,255,255);
+ comparePixel(ctx, 27,0, 255,255,255,255);
+ comparePixel(ctx, 28,0, 255,255,255,255);
+ comparePixel(ctx, 29,0, 255,255,255,255);
+ comparePixel(ctx, 30,0, 255,255,255,255);
+ comparePixel(ctx, 31,0, 255,255,255,255);
+ comparePixel(ctx, 32,0, 255,255,255,255);
+ comparePixel(ctx, 33,0, 255,255,255,255);
+ comparePixel(ctx, 34,0, 0,0,0,0);
+ comparePixel(ctx, 35,0, 0,0,0,0);
+ comparePixel(ctx, 36,0, 0,0,0,0);
+ comparePixel(ctx, 37,0, 0,0,0,0);
+ comparePixel(ctx, 38,0, 0,0,0,0);
+ comparePixel(ctx, 39,0, 0,0,0,0);
+ }
+
+ function test_lineDashOffset(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+ ctx.reset();
+ ctx.strokeStyle = "#fff";
+ ctx.lineWidth = 2;
+ var pattern = [2,2]
+ ctx.setLineDash(pattern)
+ ctx.lineDashOffset = 1
+ compare(ctx.getLineDash(), pattern);
+
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(40, 0);
+ ctx.stroke();
+
+
+ comparePixel(ctx, 0,0, 255,255,255,255);
+ comparePixel(ctx, 1,0, 255,255,255,255);
+ comparePixel(ctx, 2,0, 0,0,0,0);
+ comparePixel(ctx, 3,0, 0,0,0,0);
+ comparePixel(ctx, 4,0, 0,0,0,0);
+ comparePixel(ctx, 5,0, 0,0,0,0);
+ comparePixel(ctx, 6,0, 255,255,255,255);
+ comparePixel(ctx, 7,0, 255,255,255,255);
+ comparePixel(ctx, 8,0, 255,255,255,255);
+ comparePixel(ctx, 9,0, 255,255,255,255);
+ comparePixel(ctx, 10,0, 0,0,0,0);
+ comparePixel(ctx, 11,0, 0,0,0,0);
+ comparePixel(ctx, 12,0, 0,0,0,0);
+ comparePixel(ctx, 13,0, 0,0,0,0);
}
}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
index 22803a19ce..a3f1ab0a9b 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml
@@ -3,6 +3,8 @@ import QtQuick 2.0
CanvasTestCase {
id:testCase
name: "strokeStyle"
+ property color anotherColor: "#0000ff"
+ property color emptyColor
function init_data() { return testData("2d"); }
function test_default(row) {
var canvas = createCanvasObject(row);
@@ -46,4 +48,37 @@ CanvasTestCase {
comparePixel(ctx,0,0,255,255,255,255);
canvas.destroy()
}
+ function test_colorFromObjectToString(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+
+ ctx.reset();
+ ctx.strokeStyle = anotherColor
+ ctx.strokeStyle = "red";
+ compare(ctx.strokeStyle, "#ff0000");
+
+ ctx.strokeStyle = anotherColor
+ ctx.strokeStyle = "black";
+ compare(ctx.strokeStyle, "#000000");
+
+ ctx.strokeStyle = "white";
+ ctx.strokeStyle = anotherColor
+ compare(ctx.strokeStyle, "#0000ff");
+ canvas.destroy()
+ }
+ function test_withInvalidColor(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+
+ ctx.reset();
+ ctx.strokeStyle = emptyColor
+ compare(ctx.strokeStyle, "#000000");
+ ctx.strokeStyle = "red";
+ compare(ctx.strokeStyle, "#ff0000");
+ ctx.strokeStyle = emptyColor
+ compare(ctx.strokeStyle, "#000000");
+ ctx.strokeStyle = anotherColor;
+ compare(ctx.strokeStyle, "#0000ff");
+ canvas.destroy()
+ }
}
diff --git a/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro b/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
index c6d2a69f8c..70e5a05f8d 100644
--- a/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
+++ b/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
@@ -5,6 +5,8 @@ TARGET=tst_qquickcanvasitem
CONFIG += qmltestcase
SOURCES += tst_qquickcanvasitem.cpp
+exists($$[QT_INSTALL_PLUGINS]/imageformats): DEFINES += HAS_IMAGE_FORMATS
+
TESTDATA = data/*
OTHER_FILES += \
@@ -50,7 +52,8 @@ OTHER_FILES += \
data/transparent.png \
data/transparent50.png \
data/yellow.png \
- data/yellow75.png
+ data/yellow75.png \
+ data/tst_invalidContext.qml
CONFIG += insignificant_test # QTBUG-41043
diff --git a/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp b/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
index bde2b4809b..dad8df0682 100644
--- a/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
+++ b/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
@@ -26,4 +26,29 @@
**
****************************************************************************/
#include <QtQuickTest/quicktest.h>
-QUICK_TEST_MAIN(qquickcanvasitem)
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcontext.h>
+
+class Setup : public QObject
+{
+ Q_OBJECT
+
+public:
+ Setup() {}
+
+public slots:
+ void qmlEngineAvailable(QQmlEngine *engine)
+ {
+ engine->rootContext()->setContextProperty("hasImageFormats", QVariant(
+#ifdef HAS_IMAGE_FORMATS
+ true
+#else
+ false
+#endif
+ ));
+ }
+};
+
+QUICK_TEST_MAIN_WITH_SETUP(qquickcanvasitem, Setup)
+
+#include "tst_qquickcanvasitem.moc"
diff --git a/tests/auto/quick/qquickdesignersupport/data/Component01.qml b/tests/auto/quick/qquickdesignersupport/data/Component01.qml
new file mode 100644
index 0000000000..463417445c
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/data/Component01.qml
@@ -0,0 +1,51 @@
+import QtQuick 2.9
+import QtQuick.Window 2.3
+
+Item {
+ visible: true
+ width: 640
+ height: 480
+ objectName: "componentRoot"
+
+ Rectangle {
+ objectName: "topLevelComplete"
+ id: rectangle
+ x: 378
+ y: 91
+ width: 100
+ height: 100
+ color: "#ffffff"
+ }
+
+ Item {
+ id: element
+ x: 14
+ y: 39
+ width: 120
+ height: 120
+
+ Rectangle {
+ id: rectangle1
+ objectName: "implemented"
+ x: 43
+ y: 52
+ width: 110
+ height: 110
+ color: "#ffffff"
+
+ Component.onCompleted: {
+ rectangle1.color = "blue"
+ }
+ }
+ }
+
+ Component02 {
+ id: element1
+ x: 88
+ y: 251
+ }
+
+ Component.onCompleted: {
+ rectangle.color = "red"
+ }
+}
diff --git a/tests/auto/quick/qquickdesignersupport/data/Component02.qml b/tests/auto/quick/qquickdesignersupport/data/Component02.qml
new file mode 100644
index 0000000000..7bbad0c917
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/data/Component02.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.9
+import QtQuick.Window 2.3
+
+Item {
+ id: element1
+ width: 200
+ height: 200
+ objectName: "inner"
+
+
+ Rectangle {
+ id: rectangle2
+ objectName: "most inner"
+ x: 59
+ y: 51
+ width: 200
+ height: 200
+ color: "#ffffff"
+ }
+
+ Component.onCompleted: {
+ rectangle2.color = "green"
+ }
+}
diff --git a/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml b/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml
index 68f456af99..63d65b435c 100644
--- a/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml
+++ b/tests/auto/quick/qquickdesignersupport/data/TestComponent.qml
@@ -4,6 +4,8 @@ Item {
width: 100
height: 62
- x: Math.max(0, 200)
+ // Add a dummy dependency to parent.x to ensure that the
+ // binding stays for the test.
+ x: parent.x + Math.max(0, 200) - parent.x
}
diff --git a/tests/auto/quick/qquickdesignersupport/data/componentTest.qml b/tests/auto/quick/qquickdesignersupport/data/componentTest.qml
new file mode 100644
index 0000000000..a30cfafc90
--- /dev/null
+++ b/tests/auto/quick/qquickdesignersupport/data/componentTest.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.9
+import QtQuick.Window 2.3
+
+Item {
+ visible: true
+ width: 640
+ height: 480
+
+ Component01 {
+ id: rectangle
+ x: 205
+ y: 70
+ width: 251
+ height: 242
+ }
+
+ Item {
+ id: element
+ x: 14
+ y: 39
+ width: 285
+ height: 304
+
+ Rectangle {
+ id: rectangle1
+ x: 43
+ y: 52
+ width: 200
+ height: 200
+ color: "#ffffff"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickdesignersupport/data/test.qml b/tests/auto/quick/qquickdesignersupport/data/test.qml
index 1d43cb3b7e..6c89f15257 100644
--- a/tests/auto/quick/qquickdesignersupport/data/test.qml
+++ b/tests/auto/quick/qquickdesignersupport/data/test.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.11
Rectangle {
objectName: "rootItem"
@@ -13,7 +13,7 @@ Rectangle {
Rectangle {
objectName: "rectangleItem"
- gradient: Gradient {
+ containmentMask: Item {
}
}
diff --git a/tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro b/tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro
index 6e1ad6b95e..6212a996f1 100644
--- a/tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro
+++ b/tests/auto/quick/qquickdesignersupport/qquickdesignersupport.pro
@@ -12,4 +12,8 @@ TESTDATA = data/*
QT += core-private gui-private qml-private quick-private testlib
DISTFILES += \
- data/TestComponent.qml
+ data/TestComponent.qml \
+ data/test.qml \
+ data/componentTest.qml \
+ data/Component01.qml \
+ data/Component02.qml
diff --git a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
index 9463f7b4d5..b44977bd5a 100644
--- a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
+++ b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
@@ -61,6 +61,7 @@ private slots:
void statesPropertyChanges();
void testNotifyPropertyChangeCallBack();
void testFixResourcePathsForObjectCallBack();
+ void testComponentOnCompleteSignal();
};
void tst_qquickdesignersupport::customData()
@@ -102,7 +103,7 @@ void tst_qquickdesignersupport::customData()
QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(newItem,
view->engine()->contextForObject(newItem),
"width",
- 0));
+ nullptr));
//Check if reseting property does work after setting binding
QQuickDesignerSupportProperties::doResetProperty(newItem, view->rootContext(), "width");
@@ -136,7 +137,7 @@ void tst_qquickdesignersupport::customDataBindings()
QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
view->engine()->contextForObject(testComponent),
"x",
- 0));
+ nullptr));
QCOMPARE(testComponent->property("x").toInt(), 200);
@@ -149,7 +150,7 @@ void tst_qquickdesignersupport::customDataBindings()
QVERIFY(!QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
view->engine()->contextForObject(testComponent),
"x",
- 0));
+ nullptr));
//Reset the binding to the default
QQuickDesignerSupportProperties::doResetProperty(testComponent,
@@ -159,7 +160,7 @@ void tst_qquickdesignersupport::customDataBindings()
QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
view->engine()->contextForObject(testComponent),
"x",
- 0));
+ nullptr));
QCOMPARE(testComponent->property("x").toInt(), 200);
@@ -173,7 +174,7 @@ void tst_qquickdesignersupport::customDataBindings()
QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
view->engine()->contextForObject(testComponent),
"x",
- 0));
+ nullptr));
QCOMPARE(testComponent->property("x").toInt(), 300);
@@ -188,7 +189,7 @@ void tst_qquickdesignersupport::customDataBindings()
QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent,
view->engine()->contextForObject(testComponent),
"x",
- 0));
+ nullptr));
QCOMPARE(testComponent->property("x").toInt(), 200);
}
@@ -209,15 +210,15 @@ void tst_qquickdesignersupport::objectProperties()
//Read gradient property as QObject
- int propertyIndex = rectangleItem->metaObject()->indexOfProperty("gradient");
+ int propertyIndex = rectangleItem->metaObject()->indexOfProperty("containmentMask");
QVERIFY(propertyIndex > 0);
QMetaProperty metaProperty = rectangleItem->metaObject()->property(propertyIndex);
QVERIFY(metaProperty.isValid());
QVERIFY(QQuickDesignerSupportProperties::isPropertyQObject(metaProperty));
- QObject*gradient = QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, rectangleItem);
- QVERIFY(gradient);
+ QObject *containmentItem = QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, rectangleItem);
+ QVERIFY(containmentItem);
//The width property is not a QObject
@@ -417,7 +418,7 @@ void tst_qquickdesignersupport::statesPropertyChanges()
}
-static QObject * s_object = 0;
+static QObject * s_object = nullptr;
static QQuickDesignerSupport::PropertyName s_propertyName;
static void notifyPropertyChangeCallBackFunction(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
@@ -450,7 +451,7 @@ void tst_qquickdesignersupport::testNotifyPropertyChangeCallBack()
QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(notifyPropertyChangeCallBackPointer);
- rectangle->setProperty("gradient", QVariant::fromValue<QQuickGradient *>(gradient));
+ rectangle->setProperty("gradient", QVariant::fromValue<QJSValue>(view->engine()->newQObject(gradient)));
QVERIFY(s_object);
QCOMPARE(s_object, rootItem);
@@ -476,7 +477,7 @@ void tst_qquickdesignersupport::testFixResourcePathsForObjectCallBack()
QVERIFY(rootItem);
- s_object = 0;
+ s_object = nullptr;
QQuickDesignerSupportItems::registerFixResourcePathsForObjectCallBack(fixResourcePathsForObjectCallBackPointer);
@@ -490,6 +491,101 @@ void tst_qquickdesignersupport::testFixResourcePathsForObjectCallBack()
QCOMPARE(simpleItem , s_object);
}
+void doComponentCompleteRecursive(QObject *object)
+{
+ if (object) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(object);
+
+ if (item && DesignerSupport::isComponentComplete(item))
+ return;
+
+ DesignerSupport::emitComponentCompleteSignalForAttachedProperty(object);
+
+ QList<QObject*> childList = object->children();
+
+ if (item) {
+ foreach (QQuickItem *childItem, item->childItems()) {
+ if (!childList.contains(childItem))
+ childList.append(childItem);
+ }
+ }
+
+ foreach (QObject *child, childList)
+ doComponentCompleteRecursive(child);
+
+ if (item) {
+ static_cast<QQmlParserStatus*>(item)->componentComplete();
+ } else {
+ QQmlParserStatus *qmlParserStatus = dynamic_cast< QQmlParserStatus*>(object);
+ if (qmlParserStatus)
+ qmlParserStatus->componentComplete();
+ }
+ }
+}
+
+void tst_qquickdesignersupport::testComponentOnCompleteSignal()
+{
+ {
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("componentTest.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+ QQuickItem *rootItem = view->rootObject();
+ QVERIFY(rootItem);
+
+ QQuickItem *item = findItem<QQuickItem>(view->rootObject(), QLatin1String("topLevelComplete"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("red"));
+
+ item = findItem<QQuickItem>(view->rootObject(), QLatin1String("implemented"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("blue"));
+
+ item = findItem<QQuickItem>(view->rootObject(), QLatin1String("most inner"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("green"));
+ }
+
+ {
+ ComponentCompleteDisabler disableComponentComplete;
+
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->engine()->setOutputWarningsToStandardError(false);
+ view->setSource(testFileUrl("componentTest.qml"));
+
+ QVERIFY(view->errors().isEmpty());
+ QQuickItem *rootItem = view->rootObject();
+ QVERIFY(rootItem);
+
+ QQuickItem *item = findItem<QQuickItem>(view->rootObject(), QLatin1String("topLevelComplete"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("white"));
+
+ item = findItem<QQuickItem>(view->rootObject(), QLatin1String("implemented"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("white"));
+
+ item = findItem<QQuickItem>(view->rootObject(), QLatin1String("most inner"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("white"));
+
+ doComponentCompleteRecursive(rootItem);
+
+ item = findItem<QQuickItem>(view->rootObject(), QLatin1String("topLevelComplete"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("red"));
+
+ item = findItem<QQuickItem>(view->rootObject(), QLatin1String("implemented"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("blue"));
+
+ item = findItem<QQuickItem>(view->rootObject(), QLatin1String("most inner"));
+ QVERIFY(item);
+ QCOMPARE(item->property("color").value<QColor>(), QColor("green"));
+ }
+}
+
QTEST_MAIN(tst_qquickdesignersupport)
diff --git a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
index 6a919d048e..9d832066af 100644
--- a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
+++ b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
@@ -57,16 +57,8 @@ class TestDropTarget : public QQuickItem
{
Q_OBJECT
public:
- TestDropTarget(QQuickItem *parent = 0)
+ TestDropTarget(QQuickItem *parent = nullptr)
: QQuickItem(parent)
- , enterEvents(0)
- , moveEvents(0)
- , leaveEvents(0)
- , dropEvents(0)
- , acceptAction(Qt::MoveAction)
- , defaultAction(Qt::IgnoreAction)
- , proposedAction(Qt::IgnoreAction)
- , accept(true)
{
setFlags(ItemAcceptsDrops);
}
@@ -119,16 +111,16 @@ public:
event->setAccepted(accept);
}
- int enterEvents;
- int moveEvents;
- int leaveEvents;
- int dropEvents;
- Qt::DropAction acceptAction;
- Qt::DropAction defaultAction;
- Qt::DropAction proposedAction;
+ int enterEvents = 0;
+ int moveEvents = 0;
+ int leaveEvents = 0;
+ int dropEvents = 0;
+ Qt::DropAction acceptAction = Qt::MoveAction;
+ Qt::DropAction defaultAction = Qt::IgnoreAction;
+ Qt::DropAction proposedAction = Qt::IgnoreAction;
Qt::DropActions supportedActions;
QPointF position;
- bool accept;
+ bool accept = true;
};
class tst_QQuickDrag: public QObject
@@ -199,16 +191,16 @@ void tst_QQuickDrag::active()
evaluate<void>(item, "Drag.active = false");
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
dropTarget.reset();
evaluate<void>(item, "Drag.cancel()");
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
dropTarget.reset();
@@ -232,8 +224,8 @@ void tst_QQuickDrag::active()
evaluate<void>(item, "Drag.cancel()");
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
// Enter events aren't sent to items without the QQuickItem::ItemAcceptsDrops flag.
@@ -243,16 +235,16 @@ void tst_QQuickDrag::active()
evaluate<void>(item, "Drag.active = true");
QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
dropTarget.reset();
evaluate<void>(item, "Drag.active = false");
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
dropTarget.setFlags(QQuickItem::ItemAcceptsDrops);
@@ -271,8 +263,8 @@ void tst_QQuickDrag::active()
evaluate<void>(item, "Drag.active = false");
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
// Follow up events aren't sent to items if the enter event isn't accepted.
@@ -283,16 +275,16 @@ void tst_QQuickDrag::active()
evaluate<void>(item, "Drag.active = true");
QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
dropTarget.reset();
evaluate<void>(item, "Drag.active = false");
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
dropTarget.accept = true;
@@ -311,8 +303,8 @@ void tst_QQuickDrag::active()
evaluate<void>(item, "Drag.active = false");
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
// Events are sent to hidden or disabled items.
@@ -322,8 +314,8 @@ void tst_QQuickDrag::active()
evaluate<void>(item, "Drag.active = true");
QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
evaluate<void>(item, "Drag.active = false");
@@ -346,8 +338,8 @@ void tst_QQuickDrag::active()
evaluate<void>(item, "Drag.active = true");
QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
QCOMPARE(evaluate<bool>(item, "dragActive"), true);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
evaluate<void>(item, "Drag.active = false");
@@ -510,8 +502,8 @@ void tst_QQuickDrag::drop()
QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
@@ -522,8 +514,8 @@ void tst_QQuickDrag::drop()
QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
@@ -638,8 +630,8 @@ void tst_QQuickDrag::move()
outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
item->setPosition(QPointF(110, 50));
QCoreApplication::processEvents();
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(nullptr));
QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.moveEvents, 0);
QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 1); QCOMPARE(leftTarget .moveEvents, 0);
QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
@@ -751,7 +743,7 @@ void tst_QQuickDrag::parentChange()
QCOMPARE(dropTarget2.enterEvents, 1);
// Removing then parent item sends a leave event.
- item->setParentItem(0);
+ item->setParentItem(nullptr);
QCOMPARE(dropTarget1.enterEvents, 1);
QCOMPARE(dropTarget1.moveEvents, 1);
QCOMPARE(dropTarget1.leaveEvents, 1);
@@ -775,7 +767,7 @@ void tst_QQuickDrag::parentChange()
item->setParentItem(window2.contentItem());
QCoreApplication::processEvents();
- item->setParentItem(0);
+ item->setParentItem(nullptr);
QCoreApplication::processEvents();
QCOMPARE(dropTarget1.enterEvents, 1);
QCOMPARE(dropTarget1.moveEvents, 1);
@@ -1046,7 +1038,7 @@ class RecursingDropTarget : public TestDropTarget
{
public:
RecursingDropTarget(const QString &script, int type, QQuickItem *parent)
- : TestDropTarget(parent), script(script), type(type), item(0) {}
+ : TestDropTarget(parent), script(script), type(type), item(nullptr) {}
void setItem(QQuickItem *i) { item = i; }
diff --git a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
index fedca98205..cf01cc927b 100644
--- a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
+++ b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
@@ -185,14 +185,19 @@ void tst_QQuickDropArea::containsDrag_external()
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ const qreal dpr = window.devicePixelRatio();
+ const QPoint nativePos1 = QPoint(50, 50) * dpr;
+ const QPoint nativePos2 = QPoint(150, 50) * dpr;
+ QWindowSystemInterface::handleDrag(&window, &data, nativePos1, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, nativePos1, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
@@ -200,13 +205,15 @@ void tst_QQuickDropArea::containsDrag_external()
evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(150, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, nativePos2, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, nativePos1, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
@@ -214,13 +221,15 @@ void tst_QQuickDropArea::containsDrag_external()
evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(150, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, nativePos2, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
- QWindowSystemInterface::handleDrop(&window, &data, QPoint(150, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrop(&window, &data, nativePos2, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
}
void tst_QQuickDropArea::keys_internal()
@@ -355,80 +364,96 @@ void tst_QQuickDropArea::keys_external()
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
evaluate<void>(dropArea, "keys = \"text/x-blue\"");
QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-blue");
QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-blue");
evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
evaluate<void>(dropArea, "keys = \"text/x-red\"");
QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red");
QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red");
evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
evaluate<void>(dropArea, "keys = \"text/x-green\"");
QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-green");
QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-green");
evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
evaluate<void>(dropArea, "keys = [\"text/x-red\", \"text/x-green\"]");
QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
data.removeFormat("text/x-red");
data.removeFormat("text/x-blue");
evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
evaluate<void>(dropArea, "keys = []");
QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
data.setData("text/x-red", "red");
data.setData("text/x-blue", "blue");
QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
- QWindowSystemInterface::handleDrop(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrop(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
}
void tst_QQuickDropArea::source_internal()
@@ -460,8 +485,8 @@ void tst_QQuickDropArea::source_internal()
QQuickItem *dragSource = dropArea->findChild<QQuickItem *>("dragSource");
QVERIFY(dragSource);
- QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(nullptr));
evaluate<void>(dragItem, "Drag.active = true");
QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragItem));
@@ -469,8 +494,8 @@ void tst_QQuickDropArea::source_internal()
QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragItem));
evaluate<void>(dragItem, "Drag.active = false");
- QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(nullptr));
evaluate<void>(dropArea, "{ eventSource = null }");
@@ -482,8 +507,8 @@ void tst_QQuickDropArea::source_internal()
QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragSource));
evaluate<void>(dragItem, "Drag.active = false");
- QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
- QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(nullptr));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(nullptr));
}
// Setting a source can't be emulated using the QWindowSystemInterface API.
@@ -583,7 +608,9 @@ void tst_QQuickDropArea::position_external()
QMimeData data;
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ const qreal dpr = window.devicePixelRatio();
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50) * dpr, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
@@ -594,7 +621,8 @@ void tst_QQuickDropArea::position_external()
QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(40, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(40, 50) * dpr, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
@@ -605,7 +633,8 @@ void tst_QQuickDropArea::position_external()
QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(75, 25), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(75, 25) * dpr, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
@@ -615,7 +644,8 @@ void tst_QQuickDropArea::position_external()
QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
- QWindowSystemInterface::handleDrop(&window, &data, QPoint(75, 25), Qt::CopyAction);
+ QWindowSystemInterface::handleDrop(&window, &data, QPoint(75, 25) * dpr, Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
}
void tst_QQuickDropArea::drop_internal()
@@ -926,7 +956,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
//Same as in the first case, dropArea2 already contains a drag, dropArea1 will get the event
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
@@ -935,7 +966,8 @@ void tst_QQuickDropArea::simultaneousDrags()
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
@@ -943,7 +975,8 @@ void tst_QQuickDropArea::simultaneousDrags()
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 2);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
@@ -961,7 +994,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
@@ -972,7 +1006,8 @@ void tst_QQuickDropArea::simultaneousDrags()
// external then internal.
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
@@ -1006,7 +1041,8 @@ void tst_QQuickDropArea::simultaneousDrags()
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 2);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
@@ -1102,7 +1138,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
@@ -1112,7 +1149,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
@@ -1122,7 +1160,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
@@ -1142,7 +1181,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
- QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
@@ -1150,7 +1190,8 @@ void tst_QQuickDropArea::simultaneousDrags()
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
- QWindowSystemInterface::handleDrop(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrop(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
}
void tst_QQuickDropArea::dropStuff()
@@ -1175,8 +1216,10 @@ void tst_QQuickDropArea::dropStuff()
QCOMPARE(evaluate<QVariant>(dropArea, "array"), QVariant());
- QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
- QWindowSystemInterface::handleDrop(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
+ QWindowSystemInterface::handleDrop(&window, &data, QPoint(50, 50), Qt::CopyAction,
+ Qt::MouseButtons(), Qt::KeyboardModifiers());
QCOMPARE(evaluate<int>(dropArea, "array.byteLength"), 3);
QCOMPARE(evaluate<QByteArray>(dropArea, "array"), QByteArray("red"));
}
diff --git a/tests/auto/quick/qquickflickable/BLACKLIST b/tests/auto/quick/qquickflickable/BLACKLIST
deleted file mode 100644
index f35397f119..0000000000
--- a/tests/auto/quick/qquickflickable/BLACKLIST
+++ /dev/null
@@ -1,21 +0,0 @@
-# QTBUG-36804
-osx-10.10
-[rebound]
-osx-10.10
-[movingAndFlicking:vertical]
-osx-10.10
-[movingAndFlicking:both]
-osx-10.10
-[movingAndFlicking:horizontal]
-osx-10.10
-[stopAtBounds]
-osx-10.10
-windows developer-build
-[returnToBounds]
-osx
-[pressWhileFlicking]
-osx-10.10
-[flickVelocity]
-osx-10.10
-[nestedSliderUsingTouch:keepNeither]
-ubuntu-16.04
diff --git a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml
index 81187f3c2f..902920babc 100644
--- a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml
+++ b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml
@@ -18,6 +18,8 @@ Flickable {
height: 300
color: "yellow"
+ objectName: "yellowRect"
+
Flickable {
id: inner
objectName: "innerFlickable"
@@ -30,6 +32,7 @@ Flickable {
Rectangle {
anchors.fill: parent
anchors.margins: 100
+ objectName: "blueRect"
color: "blue"
}
MouseArea {
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index ef6e444580..65a08ce87f 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -38,6 +38,7 @@
#include <private/qqmlvaluetype_p.h>
#include <math.h>
#include "../../shared/util.h"
+#include "../shared/geometrytestutil.h"
#include "../shared/viewtestutil.h"
#include "../shared/visualtestutil.h"
@@ -56,14 +57,20 @@ class TouchDragArea : public QQuickItem
Q_PROPERTY(bool keepTouchGrab READ keepTouchGrab WRITE setKeepTouchGrab NOTIFY keepTouchGrabChanged)
public:
- TouchDragArea(QQuickItem *parent = 0)
+ TouchDragArea(QQuickItem *parent = nullptr)
: QQuickItem(parent)
, touchEvents(0)
, touchUpdates(0)
, touchReleases(0)
, ungrabs(0)
, m_active(false)
- { }
+ {
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ setAcceptTouchEvents(true);
+#else
+ setAcceptedMouseButtons(Qt::LeftButton); // not really, but we want touch events
+#endif
+ }
QPointF pos() const { return m_pos; }
@@ -196,6 +203,8 @@ private slots:
void overshoot();
void overshoot_data();
void overshoot_reentrant();
+ void synchronousDrag_data();
+ void synchronousDrag();
private:
void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
@@ -219,7 +228,7 @@ void tst_qquickflickable::create()
QQmlComponent c(&engine, testFileUrl("flickable01.qml"));
QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->isAtXBeginning(), true);
QCOMPARE(obj->isAtXEnd(), false);
QCOMPARE(obj->isAtYBeginning(), true);
@@ -244,7 +253,7 @@ void tst_qquickflickable::horizontalViewportSize()
QQmlComponent c(&engine, testFileUrl("flickable02.qml"));
QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->contentWidth(), 800.);
QCOMPARE(obj->contentHeight(), 300.);
QCOMPARE(obj->isAtXBeginning(), true);
@@ -261,7 +270,7 @@ void tst_qquickflickable::verticalViewportSize()
QQmlComponent c(&engine, testFileUrl("flickable03.qml"));
QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->contentWidth(), 200.);
QCOMPARE(obj->contentHeight(), 6000.);
QCOMPARE(obj->isAtXBeginning(), true);
@@ -278,7 +287,7 @@ void tst_qquickflickable::visibleAreaRatiosUpdate()
QQmlComponent c(&engine, testFileUrl("ratios.qml"));
QQuickItem *obj = qobject_cast<QQuickItem*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
// check initial ratio values
QCOMPARE(obj->property("heightRatioIs").toDouble(), obj->property("heightRatioShould").toDouble());
QCOMPARE(obj->property("widthRatioIs").toDouble(), obj->property("widthRatioShould").toDouble());
@@ -300,7 +309,7 @@ void tst_qquickflickable::properties()
QQmlComponent c(&engine, testFileUrl("flickable04.qml"));
QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->isInteractive(), false);
QCOMPARE(obj->boundsBehavior(), QQuickFlickable::StopAtBounds);
QCOMPARE(obj->pressDelay(), 200);
@@ -361,10 +370,10 @@ void tst_qquickflickable::rebound()
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QQuickTransition *rebound = window->rootObject()->findChild<QQuickTransition*>("rebound");
QVERIFY(rebound);
@@ -500,7 +509,7 @@ void tst_qquickflickable::pressDelay()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
QSignalSpy spy(flickable, SIGNAL(pressDelayChanged()));
@@ -528,7 +537,7 @@ void tst_qquickflickable::pressDelay()
QCOMPARE(clickedSpy.count(),0);
// On release the clicked signal should be emitted
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(150, 150));
QCOMPARE(clickedSpy.count(),1);
// Press and release position should match
@@ -546,7 +555,7 @@ void tst_qquickflickable::pressDelay()
QCOMPARE(clickedSpy.count(),0);
// On release the press, release and clicked signal should be emitted
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(180, 180));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(180, 180));
QCOMPARE(clickedSpy.count(),1);
// Press and release position should match
@@ -567,7 +576,7 @@ void tst_qquickflickable::pressDelay()
QTRY_VERIFY(!mouseArea->property("pressed").toBool());
// On release the clicked signal should *not* be emitted
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 190));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(150, 190));
QCOMPARE(clickedSpy.count(),1);
}
@@ -581,13 +590,13 @@ void tst_qquickflickable::nestedPressDelay()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(outer != 0);
+ QVERIFY(outer != nullptr);
QQuickFlickable *inner = window->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
- QVERIFY(inner != 0);
+ QVERIFY(inner != nullptr);
moveAndPress(window.data(), QPoint(150, 150));
// the MouseArea is not pressed immediately
@@ -607,7 +616,7 @@ void tst_qquickflickable::nestedPressDelay()
QVERIFY(inner->property("moving").toBool());
QVERIFY(inner->property("dragging").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(150, 150));
QVERIFY(!inner->property("dragging").toBool());
QTRY_VERIFY(!inner->property("moving").toBool());
@@ -627,7 +636,7 @@ void tst_qquickflickable::nestedPressDelay()
QVERIFY(!outer->property("moving").toBool());
QVERIFY(!outer->property("dragging").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(20, 150));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(20, 150));
QVERIFY(!inner->property("dragging").toBool());
QTRY_VERIFY(!inner->property("moving").toBool());
@@ -646,7 +655,7 @@ void tst_qquickflickable::nestedPressDelay()
QVERIFY(inner->property("moving").toBool());
QVERIFY(inner->property("dragging").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(90, 150));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(90, 150));
QVERIFY(!inner->property("dragging").toBool());
QTRY_VERIFY(!inner->property("moving").toBool());
@@ -661,13 +670,13 @@ void tst_qquickflickable::filterReplayedPress()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(outer != 0);
+ QVERIFY(outer != nullptr);
QQuickFlickable *inner = window->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
- QVERIFY(inner != 0);
+ QVERIFY(inner != nullptr);
QQuickItem *filteringMouseArea = outer->findChild<QQuickItem *>("filteringMouseArea");
QVERIFY(filteringMouseArea);
@@ -690,7 +699,7 @@ void tst_qquickflickable::filterReplayedPress()
QCOMPARE(filteringMouseArea->property("pressed").toBool(), true);
QCOMPARE(filteringMouseArea->keepMouseGrab(), true);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(150, 150));
}
@@ -704,13 +713,13 @@ void tst_qquickflickable::nestedClickThenFlick()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(outer != 0);
+ QVERIFY(outer != nullptr);
QQuickFlickable *inner = window->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
- QVERIFY(inner != 0);
+ QVERIFY(inner != nullptr);
moveAndPress(window.data(), QPoint(150, 150));
@@ -718,7 +727,7 @@ void tst_qquickflickable::nestedClickThenFlick()
QVERIFY(!outer->property("pressed").toBool());
QTRY_VERIFY(outer->property("pressed").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(150, 150));
QVERIFY(!outer->property("pressed").toBool());
@@ -736,7 +745,7 @@ void tst_qquickflickable::nestedClickThenFlick()
QVERIFY(!outer->property("moving").toBool());
QVERIFY(inner->property("moving").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(80, 100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(80, 100));
}
void tst_qquickflickable::flickableDirection()
@@ -778,13 +787,20 @@ void tst_qquickflickable::resizeContent()
QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->contentX(), 0.);
QCOMPARE(obj->contentY(), 0.);
QCOMPARE(obj->contentWidth(), 300.);
QCOMPARE(obj->contentHeight(), 300.);
+ QQuickFlickablePrivate *fp = QQuickFlickablePrivate::get(obj);
+ QSizeChangeListener sizeListener(fp->contentItem);
+
QMetaObject::invokeMethod(root, "resizeContent");
+ for (const QSize sizeOnGeometryChanged : sizeListener) {
+ // Check that we have the correct size on all signals
+ QCOMPARE(sizeOnGeometryChanged, QSize(600, 600));
+ }
QCOMPARE(obj->contentX(), 100.);
QCOMPARE(obj->contentY(), 100.);
@@ -803,15 +819,15 @@ void tst_qquickflickable::returnToBounds()
window->rootContext()->setContextProperty("setRebound", setRebound);
window->setSource(testFileUrl("resize.qml"));
window->show();
- QTest::qWaitForWindowActive(window.data());
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *obj = findItem<QQuickFlickable>(window->rootObject(), "flick");
QQuickTransition *rebound = window->rootObject()->findChild<QQuickTransition*>("rebound");
QVERIFY(rebound);
QSignalSpy reboundSpy(rebound, SIGNAL(runningChanged()));
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->contentX(), 0.);
QCOMPARE(obj->contentY(), 0.);
QCOMPARE(obj->contentWidth(), 300.);
@@ -848,10 +864,10 @@ void tst_qquickflickable::wheel()
window->setSource(testFileUrl("wheel.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flick = window->rootObject()->findChild<QQuickFlickable*>("flick");
- QVERIFY(flick != 0);
+ QVERIFY(flick != nullptr);
QQuickFlickablePrivate *fp = QQuickFlickablePrivate::get(flick);
QSignalSpy moveEndSpy(flick, SIGNAL(movementEnded()));
@@ -902,10 +918,10 @@ void tst_qquickflickable::trackpad()
window->setSource(testFileUrl("wheel.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flick = window->rootObject()->findChild<QQuickFlickable*>("flick");
- QVERIFY(flick != 0);
+ QVERIFY(flick != nullptr);
QSignalSpy moveEndSpy(flick, SIGNAL(movementEnded()));
QPoint pos(200, 200);
@@ -979,10 +995,10 @@ void tst_qquickflickable::movingAndFlicking()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QSignalSpy vMoveSpy(flickable, SIGNAL(movingVerticallyChanged()));
QSignalSpy hMoveSpy(flickable, SIGNAL(movingHorizontallyChanged()));
@@ -1142,10 +1158,10 @@ void tst_qquickflickable::movingAndDragging()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QSignalSpy vDragSpy(flickable, SIGNAL(draggingVerticallyChanged()));
QSignalSpy hDragSpy(flickable, SIGNAL(draggingHorizontallyChanged()));
@@ -1187,7 +1203,7 @@ void tst_qquickflickable::movingAndDragging()
QCOMPARE(moveStartSpy.count(), 1);
QCOMPARE(dragStartSpy.count(), 1);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, moveFrom + moveByWithoutSnapBack*3);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, moveFrom + moveByWithoutSnapBack*3);
QVERIFY(!flickable->isDragging());
QVERIFY(!flickable->isDraggingHorizontally());
@@ -1260,7 +1276,7 @@ void tst_qquickflickable::movingAndDragging()
QCOMPARE(dragStartSpy.count(), 1);
QCOMPARE(dragEndSpy.count(), 0);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, moveFrom + moveByWithSnapBack*3);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, moveFrom + moveByWithSnapBack*3);
// should now start snapping back to bounds (moving but not dragging)
QVERIFY(flickable->isMoving());
@@ -1311,10 +1327,10 @@ void tst_qquickflickable::flickOnRelease()
window->setSource(testFileUrl("flickable03.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
// Vertical with a quick press-move-release: should cause a flick in release.
QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged()));
@@ -1325,18 +1341,13 @@ void tst_qquickflickable::flickOnRelease()
// working even with small movements.
moveAndPress(window.data(), QPoint(50, 300));
QTest::mouseMove(window.data(), QPoint(50, 10), 10);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 10), 10);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50, 10), 10);
QCOMPARE(vFlickSpy.count(), 1);
// wait for any motion to end
QTRY_VERIFY(!flickable->isMoving());
-#ifdef Q_OS_MAC
-# if QT_CONFIG(opengl)
- QEXPECT_FAIL("", "QTBUG-26094 stopping on a full pixel doesn't work on OS X", Continue);
-# endif
-#endif
// Stop on a full pixel after user interaction
QCOMPARE(flickable->contentY(), (qreal)qRound(flickable->contentY()));
}
@@ -1350,10 +1361,10 @@ void tst_qquickflickable::pressWhileFlicking()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QSignalSpy vMoveSpy(flickable, SIGNAL(movingVerticallyChanged()));
QSignalSpy hMoveSpy(flickable, SIGNAL(movingHorizontallyChanged()));
@@ -1379,13 +1390,13 @@ void tst_qquickflickable::pressWhileFlicking()
QCOMPARE(hFlickSpy.count(), 0);
QCOMPARE(flickSpy.count(), 1);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(20, 50));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(20, 50));
QTRY_VERIFY(!flickable->isFlicking());
QVERIFY(!flickable->isFlickingVertically());
QVERIFY(flickable->isMoving());
QVERIFY(flickable->isMovingVertically());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(20,50));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(20,50));
QVERIFY(!flickable->isFlicking());
QVERIFY(!flickable->isFlickingVertically());
QTRY_VERIFY(!flickable->isMoving());
@@ -1400,10 +1411,10 @@ void tst_qquickflickable::disabled()
window->setSource(testFileUrl("disabled.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flick = window->rootObject()->findChild<QQuickFlickable*>("flickable");
- QVERIFY(flick != 0);
+ QVERIFY(flick != nullptr);
moveAndPress(window.data(), QPoint(50, 90));
@@ -1413,11 +1424,11 @@ void tst_qquickflickable::disabled()
QVERIFY(!flick->isMoving());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 60));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50, 60));
// verify that mouse clicks on other elements still work (QTBUG-20584)
moveAndPress(window.data(), QPoint(50, 10));
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 10));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50, 10));
QTRY_VERIFY(window->rootObject()->property("clicked").toBool());
}
@@ -1431,10 +1442,10 @@ void tst_qquickflickable::flickVelocity()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
// flick up
flick(window.data(), QPoint(20,190), QPoint(20, 50), 200);
@@ -1479,7 +1490,7 @@ void tst_qquickflickable::margins()
QQuickItem *root = window->rootObject();
QVERIFY(root);
QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root);
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
// starting state
QCOMPARE(obj->contentX(), -40.);
@@ -1558,10 +1569,10 @@ void tst_qquickflickable::cancelOnMouseGrab()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
moveAndPress(window.data(), QPoint(10, 10));
// drag out of bounds
@@ -1596,20 +1607,20 @@ void tst_qquickflickable::clickAndDragWhenTransformed()
QQuickViewTestUtil::moveMouseAway(view.data());
view->show();
QVERIFY(QTest::qWaitForWindowActive(view.data()));
- QVERIFY(view->rootObject() != 0);
+ QVERIFY(view->rootObject() != nullptr);
QQuickFlickable *flickable = view->rootObject()->findChild<QQuickFlickable*>("flickable");
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
// click outside child rect
moveAndPress(view.data(), QPoint(190, 190));
QTRY_COMPARE(flickable->property("itemPressed").toBool(), false);
- QTest::mouseRelease(view.data(), Qt::LeftButton, 0, QPoint(190, 190));
+ QTest::mouseRelease(view.data(), Qt::LeftButton, Qt::NoModifier, QPoint(190, 190));
// click inside child rect
moveAndPress(view.data(), QPoint(200, 200));
QTRY_COMPARE(flickable->property("itemPressed").toBool(), true);
- QTest::mouseRelease(view.data(), Qt::LeftButton, 0, QPoint(200, 200));
+ QTest::mouseRelease(view.data(), Qt::LeftButton, Qt::NoModifier, QPoint(200, 200));
const int threshold = qApp->styleHints()->startDragDistance();
@@ -1640,10 +1651,10 @@ void tst_qquickflickable::flickTwiceUsingTouches()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QCOMPARE(flickable->contentY(), 0.0f);
flickWithTouch(window.data(), QPoint(100, 400), QPoint(100, 240));
@@ -1771,7 +1782,7 @@ void tst_qquickflickable::nestedStopAtBounds()
QCOMPARE(outer->isMoving(), true);
QCOMPARE(inner->isDragging(), false);
QCOMPARE(inner->isMoving(), false);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
QVERIFY(!outer->isDragging());
QTRY_VERIFY(!outer->isMoving());
@@ -1793,7 +1804,7 @@ void tst_qquickflickable::nestedStopAtBounds()
QCOMPARE(outer->isMoving(), false);
QCOMPARE(inner->isDragging(), true);
QCOMPARE(inner->isMoving(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
QVERIFY(!inner->isDragging());
QTRY_VERIFY(!inner->isMoving());
@@ -1817,7 +1828,7 @@ void tst_qquickflickable::nestedStopAtBounds()
QCOMPARE(outer->isMoving(), true);
QCOMPARE(inner->isDragging(), false);
QCOMPARE(inner->isMoving(), false);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
QVERIFY(!outer->isDragging());
QTRY_VERIFY(!outer->isMoving());
@@ -1841,7 +1852,7 @@ void tst_qquickflickable::nestedStopAtBounds()
QCOMPARE(outer->isMoving(), true);
QCOMPARE(inner->isDragging(), false);
QCOMPARE(inner->isMoving(), false);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
QVERIFY(!outer->isDragging());
QTRY_VERIFY(!outer->isMoving());
@@ -1908,6 +1919,10 @@ void tst_qquickflickable::stopAtBounds()
else
QCOMPARE(transpose ? flickable->isAtYBeginning() : flickable->isAtXBeginning(), true);
+ QSignalSpy atXBeginningChangedSpy(flickable, &QQuickFlickable::atXBeginningChanged);
+ QSignalSpy atYBeginningChangedSpy(flickable, &QQuickFlickable::atYBeginningChanged);
+ QSignalSpy atXEndChangedSpy(flickable, &QQuickFlickable::atXEndChanged);
+ QSignalSpy atYEndChangedSpy(flickable, &QQuickFlickable::atYEndChanged);
// drag back towards boundary
for (int i = 0; i < 24; ++i) {
axis += invert ? threshold / 3 : -threshold / 3;
@@ -1919,6 +1934,11 @@ void tst_qquickflickable::stopAtBounds()
else
QCOMPARE(transpose ? flickable->isAtYBeginning() : flickable->isAtXBeginning(), false);
+ QCOMPARE(atXBeginningChangedSpy.count(), (!transpose && !invert) ? 1 : 0);
+ QCOMPARE(atYBeginningChangedSpy.count(), ( transpose && !invert) ? 1 : 0);
+ QCOMPARE(atXEndChangedSpy.count(), (!transpose && invert) ? 1 : 0);
+ QCOMPARE(atYEndChangedSpy.count(), ( transpose && invert) ? 1 : 0);
+
// Drag away from the aligned boundary again.
// None of the mouse movements will position the view at the boundary exactly,
// but the view should end up aligned on the boundary
@@ -1937,7 +1957,7 @@ void tst_qquickflickable::stopAtBounds()
QCOMPARE(transpose ? flickable->contentY() : flickable->contentX(), 0.0);
}
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
if (transpose) {
flickable->setContentY(invert ? 100 : 0);
@@ -1973,10 +1993,10 @@ void tst_qquickflickable::nestedMouseAreaUsingTouch()
QQuickViewTestUtil::centerOnScreen(window.data());
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QCOMPARE(flickable->contentY(), 50.0f);
flickWithTouch(window.data(), QPoint(100, 300), QPoint(100, 200));
@@ -1993,21 +2013,21 @@ void tst_qquickflickable::nestedSliderUsingTouch_data()
{
QTest::addColumn<bool>("keepMouseGrab");
QTest::addColumn<bool>("keepTouchGrab");
- QTest::addColumn<int>("updates");
+ QTest::addColumn<int>("minUpdates");
QTest::addColumn<int>("releases");
QTest::addColumn<int>("ungrabs");
QTest::newRow("keepBoth") << true << true << 8 << 1 << 0;
QTest::newRow("keepMouse") << true << false << 8 << 1 << 0;
QTest::newRow("keepTouch") << false << true << 8 << 1 << 0;
- QTest::newRow("keepNeither") << false << false << 6 << 0 << 1;
+ QTest::newRow("keepNeither") << false << false << 5 << 0 << 1;
}
void tst_qquickflickable::nestedSliderUsingTouch()
{
QFETCH(bool, keepMouseGrab);
QFETCH(bool, keepTouchGrab);
- QFETCH(int, updates);
+ QFETCH(int, minUpdates);
QFETCH(int, releases);
QFETCH(int, ungrabs);
@@ -2019,7 +2039,7 @@ void tst_qquickflickable::nestedSliderUsingTouch()
QQuickViewTestUtil::moveMouseAway(window);
window->show();
QVERIFY(QTest::qWaitForWindowActive(window));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
QVERIFY(flickable);
@@ -2043,7 +2063,7 @@ void tst_qquickflickable::nestedSliderUsingTouch()
QTest::touchEvent(window, touchDevice).release(0, p0, window);
QQuickTouchUtils::flush(window);
QTRY_COMPARE(tda->touchPointStates.first(), Qt::TouchPointPressed);
- QTRY_COMPARE(tda->touchUpdates, updates);
+ QTRY_VERIFY(tda->touchUpdates >= minUpdates);
QTRY_COMPARE(tda->touchReleases, releases);
QTRY_COMPARE(tda->ungrabs, ungrabs);
}
@@ -2058,11 +2078,11 @@ void tst_qquickflickable::pressDelayWithLoader()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
// do not crash
moveAndPress(window.data(), QPoint(150, 150));
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(150, 150));
}
// QTBUG-34507
@@ -2077,7 +2097,7 @@ void tst_qquickflickable::movementFromProgrammaticFlick()
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
// verify that the signals for movement and flicking are called in the right order
flickable->flick(0, -1000);
@@ -2132,7 +2152,7 @@ void tst_qquickflickable::ratios_smallContent()
QQuickItem *root = window->rootObject();
QVERIFY(root);
QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root);
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
//doublecheck the item, as specified by contentWidth/Height, fits in the view
//use tryCompare to allow a bit of stabilization in component's properties
@@ -2189,7 +2209,7 @@ void tst_qquickflickable::keepGrab()
QTest::mouseMove(window.data(), pos);
QTest::qWait(10);
}
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(310, 310));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(310, 310));
QTest::qWait(10);
QCOMPARE(flickable->contentX(), 0.0);
@@ -2204,7 +2224,7 @@ void tst_qquickflickable::keepGrab()
QTest::mouseMove(window.data(), pos);
QTest::qWait(10);
}
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(310, 310));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(310, 310));
QTest::qWait(10);
QVERIFY(flickable->contentX() != 0.0);
@@ -2236,11 +2256,11 @@ void tst_qquickflickable::overshoot()
flickable->setBoundsMovement(QQuickFlickable::BoundsMovement(boundsMovement));
// drag past the beginning
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(10, 10));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(10, 10));
QTest::mouseMove(window.data(), QPoint(20, 20));
QTest::mouseMove(window.data(), QPoint(30, 30));
QTest::mouseMove(window.data(), QPoint(40, 40));
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 50));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::DragOverBounds)) {
QVERIFY(flickable->property("minContentX").toReal() < 0.0);
@@ -2305,11 +2325,11 @@ void tst_qquickflickable::overshoot()
QMetaObject::invokeMethod(flickable, "reset");
// drag past the end
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(50, 50));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
QTest::mouseMove(window.data(), QPoint(40, 40));
QTest::mouseMove(window.data(), QPoint(30, 30));
QTest::mouseMove(window.data(), QPoint(20, 20));
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(10, 10));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(10, 10));
if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::DragOverBounds)) {
QVERIFY(flickable->property("maxContentX").toReal() > 200.0);
@@ -2449,6 +2469,70 @@ void tst_qquickflickable::overshoot_reentrant()
QCOMPARE(flickable->verticalOvershoot(), 25.0);
}
+void tst_qquickflickable::synchronousDrag_data()
+{
+ QTest::addColumn<bool>("synchronousDrag");
+
+ QTest::newRow("default") << false;
+ QTest::newRow("synch") << true;
+}
+
+void tst_qquickflickable::synchronousDrag()
+{
+ QFETCH(bool, synchronousDrag);
+
+ QScopedPointer<QQuickView> scopedWindow(new QQuickView);
+ QQuickView *window = scopedWindow.data();
+ window->setSource(testFileUrl("longList.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window);
+ QQuickViewTestUtil::moveMouseAway(window);
+ window->show();
+ QVERIFY(window->rootObject() != nullptr);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(flickable != nullptr);
+ QCOMPARE(flickable->synchronousDrag(), false);
+ flickable->setSynchronousDrag(synchronousDrag);
+
+ QPoint p1(100, 100);
+ QPoint p2(95, 95);
+ QPoint p3(70, 70);
+ QPoint p4(50, 50);
+ QPoint p5(30, 30);
+ QCOMPARE(flickable->contentY(), 0.0f);
+
+ // Drag via mouse
+ moveAndPress(window, p1);
+ QTest::mouseMove(window, p2);
+ QTest::mouseMove(window, p3);
+ QTest::mouseMove(window, p4);
+ QCOMPARE(flickable->contentY(), synchronousDrag ? 50.0f : 0.0f);
+ QTest::mouseMove(window, p5);
+ if (!synchronousDrag)
+ QVERIFY(flickable->contentY() < 50.0f);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p5);
+
+ // Reset to initial condition
+ flickable->setContentY(0);
+
+ // Drag via touch
+ QTest::touchEvent(window, touchDevice).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTest::touchEvent(window, touchDevice).move(0, p2, window);
+ QQuickTouchUtils::flush(window);
+ QTest::touchEvent(window, touchDevice).move(0, p3, window);
+ QQuickTouchUtils::flush(window);
+ QTest::touchEvent(window, touchDevice).move(0, p4, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(flickable->contentY(), synchronousDrag ? 50.0f : 0.0f);
+ QTest::touchEvent(window, touchDevice).move(0, p5, window);
+ QQuickTouchUtils::flush(window);
+ if (!synchronousDrag)
+ QVERIFY(flickable->contentY() < 50.0f);
+ QTest::touchEvent(window, touchDevice).release(0, p5, window);
+}
+
QTEST_MAIN(tst_qquickflickable)
#include "tst_qquickflickable.moc"
diff --git a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
index 9c892488f4..b4082b3d34 100644
--- a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
+++ b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
@@ -61,7 +61,7 @@ void tst_qquickflipable::create()
QQmlComponent c(&engine, testFileUrl("test-flipable.qml"));
QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
delete obj;
}
@@ -71,9 +71,9 @@ void tst_qquickflipable::checkFrontAndBack()
QQmlComponent c(&engine, testFileUrl("test-flipable.qml"));
QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->front() != 0);
- QVERIFY(obj->back() != 0);
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->front() != nullptr);
+ QVERIFY(obj->back() != nullptr);
delete obj;
}
@@ -83,9 +83,9 @@ void tst_qquickflipable::setFrontAndBack()
QQmlComponent c(&engine, testFileUrl("test-flipable.qml"));
QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->front() != 0);
- QVERIFY(obj->back() != 0);
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->front() != nullptr);
+ QVERIFY(obj->back() != nullptr);
QString message = c.url().toString() + ":3:1: QML Flipable: front is a write-once property";
QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
@@ -102,7 +102,7 @@ void tst_qquickflipable::flipFlipable()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("flip-flipable.qml"));
QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->side(), QQuickFlipable::Front);
obj->setProperty("flipped", QVariant(true));
QTRY_COMPARE(obj->side(), QQuickFlipable::Back);
@@ -116,7 +116,7 @@ void tst_qquickflipable::QTBUG_9161_crash()
QQuickView *window = new QQuickView;
window->setSource(testFileUrl("crash.qml"));
QQuickItem *root = window->rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
window->show();
delete window;
}
@@ -126,7 +126,7 @@ void tst_qquickflipable::QTBUG_8474_qgv_abort()
QQuickView *window = new QQuickView;
window->setSource(testFileUrl("flipable-abort.qml"));
QQuickItem *root = window->rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
window->show();
delete window;
}
diff --git a/tests/auto/quick/qquickfocusscope/BLACKLIST b/tests/auto/quick/qquickfocusscope/BLACKLIST
deleted file mode 100644
index cc3c8b6e8a..0000000000
--- a/tests/auto/quick/qquickfocusscope/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[canvasFocus]
-osx-10.11
diff --git a/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp b/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
index 5ac7fa7015..e59bb7266c 100644
--- a/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
+++ b/tests/auto/quick/qquickfocusscope/tst_qquickfocusscope.cpp
@@ -67,15 +67,15 @@ void tst_qquickfocusscope::basic()
QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
- QVERIFY(item0 != 0);
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
+ QVERIFY(item0 != nullptr);
+ QVERIFY(item1 != nullptr);
+ QVERIFY(item2 != nullptr);
+ QVERIFY(item3 != nullptr);
view->show();
view->requestActivate();
- QTest::qWaitForWindowActive(view);
+ QVERIFY(QTest::qWaitForWindowActive(view));
QTRY_COMPARE(view, qGuiApp->focusWindow());
QVERIFY(view->isTopLevel());
@@ -111,16 +111,16 @@ void tst_qquickfocusscope::nested()
QQuickFocusScope *item3 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item3"));
QQuickFocusScope *item4 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item4"));
QQuickFocusScope *item5 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item5"));
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
- QVERIFY(item4 != 0);
- QVERIFY(item5 != 0);
+ QVERIFY(item1 != nullptr);
+ QVERIFY(item2 != nullptr);
+ QVERIFY(item3 != nullptr);
+ QVERIFY(item4 != nullptr);
+ QVERIFY(item5 != nullptr);
view->show();
view->requestActivate();
- QTest::qWaitForWindowActive(view);
+ QVERIFY(QTest::qWaitForWindowActive(view));
QTRY_COMPARE(view, qGuiApp->focusWindow());
QVERIFY(item1->hasActiveFocus());
@@ -140,10 +140,10 @@ void tst_qquickfocusscope::noFocus()
QQuickRectangle *item1 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item1"));
QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
- QVERIFY(item0 != 0);
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
+ QVERIFY(item0 != nullptr);
+ QVERIFY(item1 != nullptr);
+ QVERIFY(item2 != nullptr);
+ QVERIFY(item3 != nullptr);
view->show();
view->requestActivate();
@@ -179,15 +179,15 @@ void tst_qquickfocusscope::textEdit()
QQuickTextEdit *item1 = findItem<QQuickTextEdit>(view->rootObject(), QLatin1String("item1"));
QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
QQuickTextEdit *item3 = findItem<QQuickTextEdit>(view->rootObject(), QLatin1String("item3"));
- QVERIFY(item0 != 0);
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
+ QVERIFY(item0 != nullptr);
+ QVERIFY(item1 != nullptr);
+ QVERIFY(item2 != nullptr);
+ QVERIFY(item3 != nullptr);
view->show();
view->requestActivate();
- QTest::qWaitForWindowActive(view);
+ QVERIFY(QTest::qWaitForWindowActive(view));
QTRY_COMPARE(view, qGuiApp->focusWindow());
QVERIFY(item0->hasActiveFocus());
@@ -231,16 +231,16 @@ void tst_qquickfocusscope::forceFocus()
QQuickFocusScope *item3 = findItem<QQuickFocusScope>(view->rootObject(), QLatin1String("item3"));
QQuickRectangle *item4 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item4"));
QQuickRectangle *item5 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item5"));
- QVERIFY(item0 != 0);
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
- QVERIFY(item4 != 0);
- QVERIFY(item5 != 0);
+ QVERIFY(item0 != nullptr);
+ QVERIFY(item1 != nullptr);
+ QVERIFY(item2 != nullptr);
+ QVERIFY(item3 != nullptr);
+ QVERIFY(item4 != nullptr);
+ QVERIFY(item5 != nullptr);
view->show();
view->requestActivate();
- QTest::qWaitForWindowActive(view);
+ QVERIFY(QTest::qWaitForWindowActive(view));
QTRY_COMPARE(view, qGuiApp->focusWindow());
QVERIFY(item0->hasActiveFocus());
@@ -277,7 +277,7 @@ void tst_qquickfocusscope::noParentFocus()
view->show();
view->requestActivate();
- QTest::qWaitForWindowActive(view);
+ QVERIFY(QTest::qWaitForWindowActive(view));
QTRY_COMPARE(view, qGuiApp->focusWindow());
QVERIFY(!view->rootObject()->property("focus1").toBool());
@@ -298,15 +298,15 @@ void tst_qquickfocusscope::signalEmission()
QQuickRectangle *item2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item2"));
QQuickRectangle *item3 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item3"));
QQuickRectangle *item4 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("item4"));
- QVERIFY(item1 != 0);
- QVERIFY(item2 != 0);
- QVERIFY(item3 != 0);
- QVERIFY(item4 != 0);
+ QVERIFY(item1 != nullptr);
+ QVERIFY(item2 != nullptr);
+ QVERIFY(item3 != nullptr);
+ QVERIFY(item4 != nullptr);
view->show();
view->requestActivate();
- QTest::qWaitForWindowActive(view);
+ QVERIFY(QTest::qWaitForWindowActive(view));
QTRY_COMPARE(view, qGuiApp->focusWindow());
QVariant blue(QColor("blue"));
diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
index a38b62eb16..87a5bd469a 100644
--- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
+++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
@@ -77,7 +77,7 @@ void tst_qquickfontloader::noFont()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QCOMPARE(fontObject->name(), QString(""));
QCOMPARE(fontObject->source(), QUrl(""));
QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Null);
@@ -92,7 +92,7 @@ void tst_qquickfontloader::namedFont()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QCOMPARE(fontObject->source(), QUrl(""));
QCOMPARE(fontObject->name(), QString("Helvetica"));
QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
@@ -105,7 +105,7 @@ void tst_qquickfontloader::localFont()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
@@ -119,7 +119,7 @@ void tst_qquickfontloader::failLocalFont()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString(""));
QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Error);
@@ -133,7 +133,7 @@ void tst_qquickfontloader::webFont()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
@@ -149,7 +149,7 @@ void tst_qquickfontloader::redirWebFont()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
@@ -164,7 +164,7 @@ void tst_qquickfontloader::failWebFont()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString(""));
QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Error);
@@ -179,7 +179,7 @@ void tst_qquickfontloader::changeFont()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QSignalSpy nameSpy(fontObject, SIGNAL(nameChanged()));
QSignalSpy statusSpy(fontObject, SIGNAL(statusChanged()));
@@ -218,7 +218,7 @@ void tst_qquickfontloader::changeFontSourceViaState()
QCOMPARE(&window, qGuiApp->focusWindow());
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(qvariant_cast<QObject *>(window.rootObject()->property("fontloader")));
- QVERIFY(fontObject != 0);
+ QVERIFY(fontObject != nullptr);
QTRY_COMPARE(fontObject->status(), QQuickFontLoader::Ready);
QVERIFY(fontObject->source() != QUrl(""));
QTRY_COMPARE(fontObject->name(), QString("OCRA"));
diff --git a/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp b/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp
index 6e516f51e1..ef61c45225 100644
--- a/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp
+++ b/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp
@@ -127,7 +127,7 @@ void tst_QuickFontMetrics::functions()
QFontMetricsF expected = QFontMetricsF(QFont());
QCOMPARE(metrics.elidedText(text, mode, width, flags), expected.elidedText(text, mode, width, flags));
- QCOMPARE(metrics.advanceWidth(text), expected.width(text));
+ QCOMPARE(metrics.advanceWidth(text), expected.horizontalAdvance(text));
QCOMPARE(metrics.boundingRect(text), expected.boundingRect(text));
QCOMPARE(metrics.tightBoundingRect(text), expected.tightBoundingRect(text));
}
diff --git a/tests/auto/quick/qquickframebufferobject/BLACKLIST b/tests/auto/quick/qquickframebufferobject/BLACKLIST
new file mode 100644
index 0000000000..93dd7e9d1c
--- /dev/null
+++ b/tests/auto/quick/qquickframebufferobject/BLACKLIST
@@ -0,0 +1,4 @@
+# QTBUG-65614
+b2qt
+[testThatStuffWorks]
+b2qt
diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
index d4922599be..6aff66d61e 100644
--- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
+++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
@@ -192,7 +192,8 @@ void tst_QQuickFramebufferObject::testThatStuffWorks()
item->setMsaa(msaa);
view.show();
- QTest::qWaitForWindowExposed(&view);
+ view.requestActivate();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QImage result = view.grabWindow();
@@ -231,7 +232,8 @@ void tst_QQuickFramebufferObject::testInvalidate()
item->setTextureSize(QSize(200, 200));
view.show();
- QTest::qWaitForWindowExposed(&view);
+ view.requestActivate();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QCOMPARE(frameInfo.fboSize, QSize(200, 200));
@@ -240,7 +242,7 @@ void tst_QQuickFramebufferObject::testInvalidate()
item->update();
QTRY_COMPARE(frameInfo.createFBOCount, 1);
- QCOMPARE(frameInfo.fboSize, QSize(300, 300));
+ QTRY_COMPARE(frameInfo.fboSize, QSize(300, 300));
}
QTEST_MAIN(tst_QQuickFramebufferObject)
diff --git a/tests/auto/quick/qquickgridview/BLACKLIST b/tests/auto/quick/qquickgridview/BLACKLIST
deleted file mode 100644
index 9eb9940aa5..0000000000
--- a/tests/auto/quick/qquickgridview/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[snapOneRow:horizontal, right to left]
-windows
diff --git a/tests/auto/quick/qquickgridview/data/attachedProperties.qml b/tests/auto/quick/qquickgridview/data/attachedProperties.qml
index 43d9da97fc..b1662dac44 100644
--- a/tests/auto/quick/qquickgridview/data/attachedProperties.qml
+++ b/tests/auto/quick/qquickgridview/data/attachedProperties.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquickgridview/data/margins2.qml b/tests/auto/quick/qquickgridview/data/margins2.qml
new file mode 100644
index 0000000000..346933d3c9
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/margins2.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "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 COPYRIGHT
+** OWNER OR CONTRIBUTORS 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+
+Item {
+ id: root
+ height: 1000
+ width: 1000
+
+ GridView {
+ id: grid
+ objectName: "grid"
+ height: 500
+ width: parent.width
+ topMargin: 20
+ leftMargin: 200
+ rightMargin: 200
+ bottomMargin: 30
+ cellWidth: (grid.width - grid.leftMargin - grid.rightMargin) / 3
+ model: 9
+ delegate: Rectangle {
+ border.width: 1
+ objectName: "child"
+ width: grid.cellWidth
+ height: 100
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickgridview/data/mirroring.qml b/tests/auto/quick/qquickgridview/data/mirroring.qml
index b9aff501c1..b99f50b854 100644
--- a/tests/auto/quick/qquickgridview/data/mirroring.qml
+++ b/tests/auto/quick/qquickgridview/data/mirroring.qml
@@ -2,29 +2,30 @@
// changes in right-to-left layout direction
import QtQuick 2.0
+import QtQml.Models 2.12
Rectangle {
color: "lightgray"
width: 340
height: 370
- VisualItemModel {
+ ObjectModel {
id: itemModel
objectName: "itemModel"
Rectangle {
objectName: "item1"
height: 110; width: 120; color: "#FFFEF0"
- Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text1"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item2"
height: 130; width: 150; color: "#F0FFF7"
- Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text2"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item3"
height: 170; width: 190; color: "#F4F0FF"
- Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text3"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
}
diff --git a/tests/auto/quick/qquickgridview/data/qtbug49218.qml b/tests/auto/quick/qquickgridview/data/qtbug49218.qml
new file mode 100644
index 0000000000..1a55fe5b3a
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/qtbug49218.qml
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "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 COPYRIGHT
+** OWNER OR CONTRIBUTORS 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.4
+
+Item {
+ width: 500
+ height: 160
+ visible: true
+
+ property var model1: ["1","2","3","4","5","6","7","8","9","10",
+ "11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30",
+ "31","32","33","34","a"]
+ property var model2: ["a","b","c","d","e","f","g","h","i","j","k","l","m","1"]
+ property bool useModel1: true
+
+ function changeModel() {
+ useModel1 = !useModel1
+ grid.loadModel(useModel1 ? model1 : model2)
+ }
+
+ function scrollToTop() {
+ grid.contentY = grid.originY;
+ }
+
+ GridView {
+ id: grid
+ anchors.fill: parent
+
+ model: ListModel {
+ }
+
+ onCurrentIndexChanged: {
+ positionViewAtIndex(currentIndex, GridView.Contain)
+ }
+
+ Component.onCompleted: {
+ loadModel(model1)
+ grid.currentIndex = 34
+ grid.positionViewAtIndex(34, GridView.Contain)
+ }
+
+ function loadModel(m) {
+ var remove = {};
+ var add = {};
+ var i;
+ for (i=0; i < model.count; ++i)
+ remove[model.get(i).name] = true;
+ for (i=0; i < m.length; ++i)
+ if (remove[m[i]])
+ delete remove[m[i]];
+ else
+ add[m[i]] = true;
+
+ for (i=model.count-1; i>= 0; --i)
+ if (remove[model.get(i).name])
+ model.remove(i, 1);
+
+ for (i=0; i<m.length; ++i)
+ if (add[m[i]])
+ model.insert(i, { "name": m[i] })
+ }
+
+ delegate: Rectangle {
+ height: grid.cellHeight
+ width: grid.cellWidth
+ color: GridView.isCurrentItem ? "gray" : "white"
+ Text {
+ anchors.fill: parent
+ text: name
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ grid.currentIndex = index
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickgridview/data/qtbug57225.qml b/tests/auto/quick/qquickgridview/data/qtbug57225.qml
new file mode 100644
index 0000000000..3871e5d273
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/qtbug57225.qml
@@ -0,0 +1,95 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+ width: 200
+ height: 200
+
+ property int duration: 100
+ property int count: grid.count
+
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+
+ property string nameData: name
+ property bool removalStarted: false
+ property real minX: 0
+ property real minY: 0
+
+ onXChanged: if (removalStarted) grid.recordPosition(x, y)
+ onYChanged: if (removalStarted) grid.recordPosition(x, y)
+
+ objectName: "wrapper"
+ width: 80
+ height: 80
+ border.width: 1
+ Column {
+ Text { text: index }
+ Text {
+ text: wrapper.x + ", " + wrapper.y
+ }
+ Text {
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ }
+ color: GridView.isCurrentItem ? "lightsteelblue" : "white"
+
+ GridView.onRemove: SequentialAnimation {
+ PropertyAction { target: wrapper; property: "removalStarted"; value: true }
+ PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: true }
+ NumberAnimation { target: wrapper; property: "scale"; to: 0.5; duration: root.duration; easing.type: Easing.InOutQuad }
+ PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false }
+ PropertyAction { target: grid; property: "animationDone"; value: true }
+ }
+
+ }
+ }
+
+ GridView {
+ id: grid
+
+ property int displaceTransitionsDone: 0
+ property bool animationDone: false
+ property point minimumPosition: Qt.point(0, 0)
+
+ signal delegateMoved(real x, real y)
+
+ objectName: "grid"
+ focus: true
+ anchors.fill: parent
+ cacheBuffer: 0
+ cellWidth: 80
+ cellHeight: 80
+ model: testModel
+ delegate: myDelegate
+
+ displaced: Transition {
+ id: transition
+ SequentialAnimation {
+ NumberAnimation {
+ properties: "x,y"
+ duration: root.duration
+ easing.type: Easing.OutBounce
+ }
+ ScriptAction { script: grid.displaceTransitionsDone += 1 }
+ }
+ }
+
+ function recordPosition(index, x, y) {
+ if (x < minimumPosition.x || y < minimumPosition.y) {
+ minimumPosition = Qt.point(x, y)
+ }
+ }
+ }
+
+ Rectangle {
+ anchors.fill: grid
+ color: "lightsteelblue"
+ opacity: 0.2
+ }
+}
+
diff --git a/tests/auto/quick/qquickgridview/data/releaseItems.qml b/tests/auto/quick/qquickgridview/data/releaseItems.qml
new file mode 100644
index 0000000000..19d58550a4
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/releaseItems.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+
+GridView {
+ width: 400
+ height: 400
+ model: 100
+ delegate: Rectangle {
+ height: 100; width: 100
+ color: index % 2 ? "lightsteelblue" : "lightgray"
+ }
+ contentHeight: contentItem.children.length * 40
+}
diff --git a/tests/auto/quick/qquickgridview/data/unrequestedItems.qml b/tests/auto/quick/qquickgridview/data/unrequestedItems.qml
index bedb90b849..4afe5ac8b3 100644
--- a/tests/auto/quick/qquickgridview/data/unrequestedItems.qml
+++ b/tests/auto/quick/qquickgridview/data/unrequestedItems.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Item {
width: 240
@@ -38,7 +39,7 @@ Item {
}
- VisualDataModel {
+ DelegateModel {
id: visualModel
delegate: myDelegate
diff --git a/tests/auto/quick/qquickgridview/qquickgridview.pro b/tests/auto/quick/qquickgridview/qquickgridview.pro
index 3c33cc78fb..5051f8bc62 100644
--- a/tests/auto/quick/qquickgridview/qquickgridview.pro
+++ b/tests/auto/quick/qquickgridview/qquickgridview.pro
@@ -10,5 +10,5 @@ include (../shared/util.pri)
TESTDATA = data/*
-QT += core-private gui-private qml-private quick-private testlib
+QT += core-private gui-private qml-private quick-private testlib qmltest
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index 1acc36c9b0..3b704d7fa4 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <QtCore/qstringlistmodel.h>
#include <QtQuick/qquickview.h>
+#include <QtQuickTest/QtQuickTest>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
@@ -46,6 +47,8 @@
#include <QtGui/qguiapplication.h>
#include "qplatformdefs.h"
+#include <math.h>
+
Q_DECLARE_METATYPE(QQuickGridView::Flow)
Q_DECLARE_METATYPE(Qt::LayoutDirection)
Q_DECLARE_METATYPE(QQuickItemView::VerticalLayoutDirection)
@@ -151,6 +154,8 @@ private slots:
void multipleTransitions();
void multipleTransitions_data();
void multipleDisplaced();
+ void regression_QTBUG_57225();
+ void regression_QTBUG_57225_data();
void inserted_leftToRight_RtL_TtB();
void inserted_leftToRight_RtL_TtB_data();
@@ -206,9 +211,11 @@ private slots:
void contentHeightWithDelayRemove();
void QTBUG_45640();
+ void QTBUG_49218();
void QTBUG_48870_fastModelUpdates();
void keyNavigationEnabled();
+ void releaseItems();
private:
QList<int> toIntList(const QVariantList &list);
@@ -281,7 +288,7 @@ private:
if (m_view) {
if (QString(QTest::currentTestFunction()) != testForView) {
delete m_view;
- m_view = 0;
+ m_view = nullptr;
} else {
m_view->setSource(QUrl());
return m_view;
@@ -310,7 +317,7 @@ private:
QString testForView;
};
-tst_QQuickGridView::tst_QQuickGridView() : m_view(0)
+tst_QQuickGridView::tst_QQuickGridView() : m_view(nullptr)
{
}
@@ -320,7 +327,7 @@ void tst_QQuickGridView::init()
if (m_view && QString(QTest::currentTestFunction()) != testForView) {
testForView = QString();
delete m_view;
- m_view = 0;
+ m_view = nullptr;
}
#endif
}
@@ -330,7 +337,7 @@ void tst_QQuickGridView::cleanupTestCase()
#ifdef SHARE_VIEWS
testForView = QString();
delete m_view;
- m_view = 0;
+ m_view = nullptr;
#endif
}
@@ -354,10 +361,10 @@ void tst_QQuickGridView::items()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QTRY_COMPARE(gridview->count(), model.count());
QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
@@ -365,10 +372,10 @@ void tst_QQuickGridView::items()
for (int i = 0; i < model.count(); ++i) {
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -402,17 +409,17 @@ void tst_QQuickGridView::changed()
qApp->processEvents();
QQuickFlickable *gridview = findItem<QQuickFlickable>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
model.modifyItem(1, "Will", "9876");
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(1));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(1));
delete window;
@@ -433,10 +440,10 @@ void tst_QQuickGridView::inserted_basic()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
model.insertItem(1, "Will", "9876");
@@ -444,10 +451,10 @@ void tst_QQuickGridView::inserted_basic()
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(1));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(1));
// Checks that onAdd is called
@@ -466,10 +473,10 @@ void tst_QQuickGridView::inserted_basic()
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(0));
number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(0));
QTRY_COMPARE(gridview->currentIndex(), 1);
@@ -520,16 +527,16 @@ void tst_QQuickGridView::inserted_defaultLayout(QQuickGridView::Flow flow,
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
if (flow == QQuickGridView::FlowTopToBottom) {
insertIndex = insertIndex_ttb;
insertCount = insertCount_ttb;
}
if (setContentPos(gridview, contentYRowOffset))
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QList<QPair<QString, QString> > newData;
for (int i=0; i<insertCount; i++)
@@ -565,7 +572,7 @@ void tst_QQuickGridView::inserted_defaultLayout(QQuickGridView::Flow flow,
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
QCOMPARE(item->position(), expectedItemPos(gridview, i, rowOffsetAfterMove));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), model.name(i));
}
@@ -710,18 +717,18 @@ void tst_QQuickGridView::insertBeforeVisible()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
gridview->setCacheBuffer(cacheBuffer);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// trigger a refill (not just setting contentY) so that the visibleItems grid is updated
int firstVisibleIndex = 12; // move to an index where the top item is not visible
gridview->setContentY(firstVisibleIndex/3 * 60.0);
gridview->setCurrentIndex(firstVisibleIndex);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QTRY_COMPARE(gridview->currentIndex(), firstVisibleIndex);
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
@@ -738,7 +745,7 @@ void tst_QQuickGridView::insertBeforeVisible()
// now, moving to the top of the view should position the inserted items correctly
int itemsOffsetAfterMove = (insertCount / 3) * -60.0;
gridview->setCurrentIndex(0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QTRY_COMPARE(gridview->currentIndex(), 0);
QTRY_COMPARE(gridview->contentY(), 0.0 + itemsOffsetAfterMove);
@@ -750,7 +757,7 @@ void tst_QQuickGridView::insertBeforeVisible()
QCOMPARE(item->x(), (i%3)*80.0);
QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -794,19 +801,19 @@ void tst_QQuickGridView::removed_basic()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
model.removeItem(1);
QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(1));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(1));
@@ -828,10 +835,10 @@ void tst_QQuickGridView::removed_basic()
QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(0));
number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(0));
@@ -884,7 +891,7 @@ void tst_QQuickGridView::removed_basic()
QTRY_VERIFY(gridview->currentItem() != oldCurrent);
gridview->setContentY(0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// Confirm items positioned correctly
itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -907,7 +914,7 @@ void tst_QQuickGridView::removed_basic()
model.removeItem(20);
QTRY_COMPARE(gridview->currentIndex(), 20);
- QTRY_VERIFY(gridview->currentItem() != 0);
+ QTRY_VERIFY(gridview->currentItem() != nullptr);
// remove item before current, but visible
gridview->setCurrentIndex(8);
@@ -950,9 +957,9 @@ void tst_QQuickGridView::removed_defaultLayout(QQuickGridView::Flow flow,
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
if (flow == QQuickGridView::FlowTopToBottom) {
removeIndex = removeIndex_ttb;
@@ -960,7 +967,7 @@ void tst_QQuickGridView::removed_defaultLayout(QQuickGridView::Flow flow,
firstVisible = firstVisible_ttb;
}
if (setContentPos(gridview, contentYRowOffset))
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
model.removeItems(removeIndex, removeCount);
gridview->forceLayout();
@@ -991,7 +998,7 @@ void tst_QQuickGridView::removed_defaultLayout(QQuickGridView::Flow flow,
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
QCOMPARE(item->position(), expectedItemPos(gridview, i, rowOffsetAfterMove));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -1138,7 +1145,7 @@ void tst_QQuickGridView::removed_defaultLayout_data()
QTest::newRow("remove multiple, after visible, content not at start")
<< 2.0 // show 6-23
<< 16+4 << 5
- << 15+10 << 7
+ << 15 << 7
<< 0.0 << "Item6" << "Item10";
QTest::newRow("remove multiple, mix of items from within and after visible items")
@@ -1167,16 +1174,16 @@ void tst_QQuickGridView::addOrRemoveBeforeVisible()
window->setSource(testFileUrl("gridview1.qml"));
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
QTRY_COMPARE(name->text(), QString("Item0"));
gridview->setCurrentIndex(0);
qApp->processEvents();
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// scroll down until item 0 is no longer drawn
// (bug not triggered if we just move using content y, since that doesn't
@@ -1187,7 +1194,7 @@ void tst_QQuickGridView::addOrRemoveBeforeVisible()
QTRY_COMPARE(gridview->currentIndex(), 24);
QTRY_COMPARE(gridview->contentY(), 220.0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 0)); // 0 shouldn't be visible
if (doAdd) {
@@ -1245,10 +1252,10 @@ void tst_QQuickGridView::clear()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QVERIFY(gridview != 0);
+ QVERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
model.clear();
gridview->forceLayout();
@@ -1263,7 +1270,7 @@ void tst_QQuickGridView::clear()
model.addItem("New", "1");
gridview->forceLayout();
QTRY_COMPARE(gridview->count(), 1);
- QVERIFY(gridview->currentItem() != 0);
+ QVERIFY(gridview->currentItem() != nullptr);
QCOMPARE(gridview->currentIndex(), 0);
delete window;
@@ -1298,13 +1305,13 @@ void tst_QQuickGridView::moved_defaultLayout(QQuickGridView::Flow flow,
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QQuickItem *currentItem = gridview->currentItem();
- QTRY_VERIFY(currentItem != 0);
+ QTRY_VERIFY(currentItem != nullptr);
if (flow == QQuickGridView::FlowTopToBottom) {
from = from_ttb;
@@ -1312,10 +1319,10 @@ void tst_QQuickGridView::moved_defaultLayout(QQuickGridView::Flow flow,
count = count_ttb;
}
if (setContentPos(gridview, contentYRowOffset))
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
model.moveItems(from, to, count);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// Confirm items positioned correctly and indexes correct
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
@@ -1339,7 +1346,7 @@ void tst_QQuickGridView::moved_defaultLayout(QQuickGridView::Flow flow,
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
QCOMPARE(item->position(), expectedItemPos(gridview, i, rowOffsetAfterMove));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
// current index should have been updated
@@ -1553,8 +1560,8 @@ void tst_QQuickGridView::multipleChanges(bool condensed)
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(gridview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
for (int i=0; i<changes.count(); i++) {
switch (changes[i].type) {
@@ -1582,10 +1589,10 @@ void tst_QQuickGridView::multipleChanges(bool condensed)
break;
}
if (condensed) {
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
}
}
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QCOMPARE(gridview->count(), newCount);
QCOMPARE(gridview->count(), model.count());
@@ -1594,16 +1601,16 @@ void tst_QQuickGridView::multipleChanges(bool condensed)
QQuickText *name;
QQuickText *number;
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i=0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
+ QVERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -1798,7 +1805,7 @@ void tst_QQuickGridView::swapWithFirstItem()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
// ensure content position is stable
gridview->setContentY(0);
@@ -1814,7 +1821,7 @@ void tst_QQuickGridView::currentIndex()
for (int i = 0; i < 60; i++)
initModel.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setGeometry(0,0,240,320);
window->show();
@@ -1827,17 +1834,18 @@ void tst_QQuickGridView::currentIndex()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QVERIFY(gridview != 0);
- QTRY_VERIFY(!QQuickItemPrivate::get(gridview)->polishScheduled);
+ QVERIFY(gridview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
// currentIndex is initialized to 35
// currentItem should be in view
QCOMPARE(gridview->currentIndex(), 35);
QCOMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 35));
- QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
+ // Wait for possible animation to finish
+ QTRY_COMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
QCOMPARE(gridview->contentY(), 400.0);
// changing model should reset currentIndex to 0
@@ -1914,7 +1922,7 @@ void tst_QQuickGridView::noCurrentIndex()
for (int i = 0; i < 60; i++)
model.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setGeometry(0,0,240,320);
QQmlContext *ctxt = window->rootContext();
@@ -1926,10 +1934,10 @@ void tst_QQuickGridView::noCurrentIndex()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QVERIFY(gridview != 0);
+ QVERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// current index should be -1
QCOMPARE(gridview->currentIndex(), -1);
@@ -1967,17 +1975,17 @@ void tst_QQuickGridView::keyNavigation()
window->rootContext()->setContextProperty("testModel", &model);
window->setSource(testFileUrl("gridview1.qml"));
window->show();
- QTest::qWaitForWindowActive(window);
+ QVERIFY(QTest::qWaitForWindowActive(window));
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
gridview->setFlow(flow);
gridview->setLayoutDirection(layoutDirection);
gridview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
window->requestActivate();
- QTest::qWaitForWindowActive(window);
+ QVERIFY(QTest::qWaitForWindowActive(window));
QTRY_COMPARE(qGuiApp->focusWindow(), window);
QCOMPARE(gridview->currentIndex(), 0);
@@ -2176,10 +2184,10 @@ void tst_QQuickGridView::changeFlow()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
// Confirm items positioned correctly and indexes correct
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -2190,10 +2198,10 @@ void tst_QQuickGridView::changeFlow()
QTRY_COMPARE(item->x(), qreal((i%3)*80));
QTRY_COMPARE(item->y(), qreal((i/3)*60));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -2208,10 +2216,10 @@ void tst_QQuickGridView::changeFlow()
QTRY_COMPARE(item->x(), qreal((i/5)*80));
QTRY_COMPARE(item->y(), qreal((i%5)*60));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -2226,10 +2234,10 @@ void tst_QQuickGridView::changeFlow()
QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width()));
QTRY_COMPARE(item->y(), qreal((i%5)*60));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
gridview->setContentX(100);
@@ -2246,10 +2254,10 @@ void tst_QQuickGridView::changeFlow()
QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80));
QTRY_COMPARE(item->y(), qreal((i/3)*60));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -2262,7 +2270,7 @@ void tst_QQuickGridView::defaultValues()
QQmlComponent c(&engine, testFileUrl("gridview3.qml"));
QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
- QTRY_VERIFY(obj != 0);
+ QTRY_VERIFY(obj != nullptr);
QTRY_COMPARE(obj->model(), QVariant());
QTRY_VERIFY(!obj->delegate());
QTRY_COMPARE(obj->currentIndex(), -1);
@@ -2289,14 +2297,14 @@ void tst_QQuickGridView::properties()
QQmlComponent c(&engine, testFileUrl("gridview2.qml"));
QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
- QTRY_VERIFY(obj != 0);
+ QTRY_VERIFY(obj != nullptr);
QTRY_VERIFY(obj->model() != QVariant());
- QTRY_VERIFY(obj->delegate() != 0);
+ QTRY_VERIFY(obj->delegate() != nullptr);
QTRY_COMPARE(obj->currentIndex(), 0);
- QTRY_VERIFY(obj->currentItem() != 0);
+ QTRY_VERIFY(obj->currentItem() != nullptr);
QTRY_COMPARE(obj->count(), 4);
- QTRY_VERIFY(obj->highlight() != 0);
- QTRY_VERIFY(obj->highlightItem() != 0);
+ QTRY_VERIFY(obj->highlight() != nullptr);
+ QTRY_VERIFY(obj->highlightItem() != nullptr);
QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
QTRY_COMPARE(obj->flow(), QQuickGridView::FlowLeftToRight);
QTRY_COMPARE(obj->isWrapEnabled(), true);
@@ -2481,10 +2489,10 @@ void tst_QQuickGridView::positionViewAtBeginningEnd()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// positionViewAtBeginning
gridview->setContentY(150);
@@ -2568,13 +2576,13 @@ void tst_QQuickGridView::positionViewAtIndex()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
window->rootObject()->setProperty("enforceRange", enforceRange);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
if (topToBottom)
gridview->setContentX(initContentPos);
@@ -2680,7 +2688,7 @@ void tst_QQuickGridView::snapping()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
gridview->setHeight(220);
QCOMPARE(gridview->height(), 220.);
@@ -2709,12 +2717,12 @@ void tst_QQuickGridView::mirroring()
QQuickView *windowA = createView();
windowA->setSource(testFileUrl("mirroring.qml"));
QQuickGridView *gridviewA = findItem<QQuickGridView>(windowA->rootObject(), "view");
- QTRY_VERIFY(gridviewA != 0);
+ QTRY_VERIFY(gridviewA != nullptr);
QQuickView *windowB = createView();
windowB->setSource(testFileUrl("mirroring.qml"));
QQuickGridView *gridviewB = findItem<QQuickGridView>(windowB->rootObject(), "view");
- QTRY_VERIFY(gridviewA != 0);
+ QTRY_VERIFY(gridviewA != nullptr);
qApp->processEvents();
QList<QString> objectNames;
@@ -2781,16 +2789,16 @@ void tst_QQuickGridView::resetModel()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QTRY_COMPARE(gridview->count(), model.rowCount());
for (int i = 0; i < model.rowCount(); ++i) {
QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
- QTRY_VERIFY(display != 0);
+ QTRY_VERIFY(display != nullptr);
QTRY_COMPARE(display->text(), strings.at(i));
}
@@ -2802,7 +2810,7 @@ void tst_QQuickGridView::resetModel()
for (int i = 0; i < model.rowCount(); ++i) {
QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
- QTRY_VERIFY(display != 0);
+ QTRY_VERIFY(display != nullptr);
QTRY_COMPARE(display->text(), strings.at(i));
}
@@ -2825,18 +2833,18 @@ void tst_QQuickGridView::enforceRange()
window->setSource(testFileUrl("gridview-enforcerange.qml"));
window->show();
qApp->processEvents();
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
QTRY_COMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
// view should be positioned at the top of the range.
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
@@ -2844,10 +2852,10 @@ void tst_QQuickGridView::enforceRange()
QTRY_COMPARE(gridview->contentY(), -100.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(0));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(0));
// Check currentIndex is updated when contentItem moves
@@ -2883,17 +2891,17 @@ void tst_QQuickGridView::enforceRange_rightToLeft()
window->setSource(testFileUrl("gridview-enforcerange.qml"));
window->show();
QTRY_VERIFY(window->isExposed());
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QCOMPARE(gridview->preferredHighlightBegin(), 100.0);
QCOMPARE(gridview->preferredHighlightEnd(), 100.0);
QCOMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
// view should be positioned at the top of the range.
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
@@ -2902,10 +2910,10 @@ void tst_QQuickGridView::enforceRange_rightToLeft()
QTRY_COMPARE(gridview->contentY(), 0.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(0));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(0));
// Check currentIndex is updated when contentItem moves
@@ -2934,7 +2942,7 @@ void tst_QQuickGridView::QTBUG_8456()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QTRY_COMPARE(gridview->currentIndex(), 0);
@@ -2951,10 +2959,10 @@ void tst_QQuickGridView::manualHighlight()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QTRY_COMPARE(gridview->currentIndex(), 0);
QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
@@ -3012,14 +3020,14 @@ void tst_QQuickGridView::footer()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
gridview->setFlow(flow);
gridview->setLayoutDirection(layoutDirection);
gridview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
QVERIFY(footer);
@@ -3072,7 +3080,7 @@ void tst_QQuickGridView::footer()
// if header is toggled, it shouldn't affect the footer position
window->rootObject()->setProperty("showHeader", true);
- QVERIFY(findItem<QQuickItem>(contentItem, "header") != 0);
+ QVERIFY(findItem<QQuickItem>(contentItem, "header") != nullptr);
QTRY_COMPARE(footer->position(), posWhenNoItems);
window->rootObject()->setProperty("showHeader", false);
@@ -3209,9 +3217,9 @@ void tst_QQuickGridView::initialZValues()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QVERIFY(gridview->currentItem());
QTRY_COMPARE(gridview->currentItem()->z(), gridview->property("itemZ").toReal());
@@ -3261,14 +3269,14 @@ void tst_QQuickGridView::header()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
gridview->setFlow(flow);
gridview->setLayoutDirection(layoutDirection);
gridview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickText *header = findItem<QQuickText>(contentItem, "header");
QVERIFY(header);
@@ -3289,7 +3297,7 @@ void tst_QQuickGridView::header()
QCOMPARE(item->position(), firstDelegatePos);
model.clear();
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QCOMPARE(header->position(), initialHeaderPos); // header should stay where it is
if (flow == QQuickGridView::FlowLeftToRight)
QCOMPARE(gridview->contentHeight(), header->height());
@@ -3338,11 +3346,11 @@ void tst_QQuickGridView::header()
qApp->processEvents();
gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
gridview->setFlow(flow);
gridview->setLayoutDirection(layoutDirection);
gridview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
gridview->setWidth(240);
gridview->setHeight(320);
@@ -3483,14 +3491,14 @@ void tst_QQuickGridView::extents()
qApp->processEvents();
QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject());
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
gridview->setFlow(flow);
gridview->setLayoutDirection(layoutDirection);
gridview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
QVERIFY(header);
@@ -3599,10 +3607,10 @@ void tst_QQuickGridView::resetModel_headerFooter()
qApp->processEvents();
QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject());
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
QVERIFY(header);
@@ -3645,10 +3653,10 @@ void tst_QQuickGridView::resizeViewAndRepaint()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// item at index 10 should not be currently visible
QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
@@ -3721,15 +3729,15 @@ void tst_QQuickGridView::resizeGrid()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
// set the width to slightly larger than 3 items across, to test
// items are aligned correctly in right-to-left
window->rootObject()->setWidth(260);
window->rootObject()->setHeight(320);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QCOMPARE(gridview->contentX(), initialContentPos.x());
QCOMPARE(gridview->contentY(), initialContentPos.y());
@@ -3746,14 +3754,14 @@ void tst_QQuickGridView::resizeGrid()
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
QCOMPARE(item->position(), expectedItemPos(gridview, i, 0));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), model.name(i));
}
// change from 3x5 grid to 4x7
window->rootObject()->setWidth(window->rootObject()->width() + 80);
window->rootObject()->setHeight(window->rootObject()->height() + 60*2);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// other than in LeftToRight+RightToLeft layout, the first item should not move
// if view is resized
@@ -3778,7 +3786,7 @@ void tst_QQuickGridView::resizeGrid()
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
QCOMPARE(item->position(), expectedItemPos(gridview, i, 0));
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), model.name(i));
}
@@ -3855,10 +3863,10 @@ void tst_QQuickGridView::changeColumnCount()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
// a single column of 6 items are visible
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -3872,7 +3880,7 @@ void tst_QQuickGridView::changeColumnCount()
// now 6x3 grid is visible, plus 1 extra below for refill
gridview->setWidth(240);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
QCOMPARE(itemCount, 6*3 + 1);
for (int i = 0; i < model.count() && i < itemCount; ++i) {
@@ -3884,7 +3892,7 @@ void tst_QQuickGridView::changeColumnCount()
// back to single column
gridview->setWidth(100);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
QCOMPARE(itemCount, 6);
for (int i = 0; i < model.count() && i < itemCount; ++i) {
@@ -3932,14 +3940,14 @@ void tst_QQuickGridView::indexAt_itemAt()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QTRY_COMPARE(gridview->count(), model.count());
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
if (index >= 0) {
item = findItem<QQuickItem>(contentItem, "wrapper", index);
QVERIFY(item);
@@ -4071,7 +4079,7 @@ void tst_QQuickGridView::attachedProperties_QTBUG_32836()
qApp->processEvents();
QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject());
- QVERIFY(gridview != 0);
+ QVERIFY(gridview != nullptr);
QQuickItem *header = gridview->headerItem();
QVERIFY(header);
@@ -4129,10 +4137,10 @@ void tst_QQuickGridView::margins()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QCOMPARE(gridview->contentX(), -30.);
QCOMPARE(gridview->originX(), 0.);
@@ -4192,10 +4200,10 @@ void tst_QQuickGridView::margins()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QTRY_COMPARE(gridview->contentX(), -240+50.);
QTRY_COMPARE(gridview->originX(), -100. * 10);
@@ -4210,7 +4218,7 @@ void tst_QQuickGridView::margins()
// remove item before visible and check that left margin is maintained
// and originX is updated
gridview->setContentX(-400);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
model.removeItems(0, 4);
gridview->forceLayout();
QTRY_COMPARE(model.count(), gridview->count());
@@ -4241,6 +4249,23 @@ void tst_QQuickGridView::margins()
delete window;
}
+ {
+ QQuickView *window = createView();
+
+ window->setSource(testFileUrl("margins2.qml"));
+ window->show();
+ qApp->processEvents();
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
+ QVERIFY(gridview != nullptr);
+ QQuickItem *contentItem = gridview->contentItem();
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
+ QCOMPARE(contentItem->x(), 200);
+ QCOMPARE(contentItem->y(), 20);
+
+ delete window;
+ }
}
void tst_QQuickGridView::creationContext()
@@ -4312,15 +4337,15 @@ void tst_QQuickGridView::snapToRow()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
gridview->setFlow(flow);
gridview->setLayoutDirection(layoutDirection);
gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
qreal origContentY = gridview->contentY();
qreal origContentX = gridview->contentX();
@@ -4333,7 +4358,7 @@ void tst_QQuickGridView::snapToRow()
// click to stop it. Otherwise we wouldn't know how much further it will go. We don't want to it
// to hit the endExtent, yet.
- QTest::mouseClick(window, Qt::LeftButton, 0, flickEnd);
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, flickEnd);
QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
if (flow == QQuickGridView::FlowLeftToRight)
@@ -4380,24 +4405,34 @@ void tst_QQuickGridView::snapOneRow_data()
QTest::addColumn<qreal>("snapAlignment");
QTest::addColumn<qreal>("endExtent");
QTest::addColumn<qreal>("startExtent");
+ QTest::addColumn<qreal>("flickSlowdown");
QTest::newRow("vertical, left to right") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 240.0 << 0.0;
+ << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 240.0 << 0.0 << 1.0;
QTest::newRow("horizontal, left to right") << QQuickGridView::FlowTopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
- << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 240.0 << 0.0;
+ << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 240.0 << 0.0 << 1.0;
QTest::newRow("horizontal, right to left") << QQuickGridView::FlowTopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 << -240.0;
+ << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 << -240.0 << 1.0;
QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 340.0 << -20.0;
+ << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 340.0 << -20.0 << 1.0;
QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::FlowTopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 340.0 << -20.0;
+ << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 340.0 << -20.0 << 1.0;
QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::FlowTopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 - 100.0 << -220.0;
+ << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 - 100.0 << -220.0 << 1.0;
+
+ // Using e.g. 120 rather than 95 always went to the next row.
+ // Ensure this further movement has the same behavior
+ QTest::newRow("vertical, left to right, no more blindspot") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
+ << QPoint(20, 160) << QPoint(20, 95) << 100.0 << 240.0 << 0.0 << 4.0;
+
+ // StrictlyEnforceRange should not override valid SnapOneItem decisions
+ QTest::newRow("vertical, left to right, no more blindspot, enforce range") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(20, 160) << QPoint(20, 95) << 100.0 << 340.0 << -20.0 << 4.0;
}
void tst_QQuickGridView::snapOneRow()
@@ -4410,6 +4445,9 @@ void tst_QQuickGridView::snapOneRow()
QFETCH(qreal, snapAlignment);
QFETCH(qreal, endExtent);
QFETCH(qreal, startExtent);
+ QFETCH(qreal, flickSlowdown);
+
+ qreal flickDuration = 180 * flickSlowdown;
QQuickView *window = getView();
QQuickViewTestUtil::moveMouseAway(window);
@@ -4419,20 +4457,20 @@ void tst_QQuickGridView::snapOneRow()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
gridview->setFlow(flow);
gridview->setLayoutDirection(layoutDirection);
gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QQuickItem *contentItem = gridview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QSignalSpy currentIndexSpy(gridview, SIGNAL(currentIndexChanged()));
// confirm that a flick hits next row boundary
- flick(window, flickStart, flickEnd, 180);
+ flick(window, flickStart, flickEnd, flickDuration);
QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
if (flow == QQuickGridView::FlowLeftToRight)
QCOMPARE(gridview->contentY(), snapAlignment);
@@ -4446,7 +4484,7 @@ void tst_QQuickGridView::snapOneRow()
// flick to end
do {
- flick(window, flickStart, flickEnd, 180);
+ flick(window, flickStart, flickEnd, flickDuration);
QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
} while (flow == QQuickGridView::FlowLeftToRight
? !gridview->isAtYEnd()
@@ -4464,7 +4502,7 @@ void tst_QQuickGridView::snapOneRow()
// flick to start
do {
- flick(window, flickEnd, flickStart, 180);
+ flick(window, flickEnd, flickStart, flickDuration);
QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
} while (flow == QQuickGridView::FlowLeftToRight
? !gridview->isAtYBeginning()
@@ -4500,10 +4538,10 @@ void tst_QQuickGridView::unaligned()
qApp->processEvents();
QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject());
- QVERIFY(gridview != 0);
+ QVERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
for (int i = 0; i < 10; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
@@ -4516,7 +4554,7 @@ void tst_QQuickGridView::unaligned()
// appending
for (int i = 10; i < 18; ++i) {
model.addItem("Item" + QString::number(i), "");
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
@@ -4525,7 +4563,7 @@ void tst_QQuickGridView::unaligned()
// inserting
for (int i = 0; i < 10; ++i) {
model.insertItem(i, "Item" + QString::number(i), "");
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
@@ -4536,7 +4574,7 @@ void tst_QQuickGridView::unaligned()
gridview->forceLayout();
QTRY_COMPARE(model.count(), gridview->count());
for (int i = 0; i < 18; ++i) {
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
QCOMPARE(item->x(), qreal(i%9)*gridview->cellWidth());
QCOMPARE(item->y(), qreal(i/9)*gridview->cellHeight());
@@ -4586,7 +4624,7 @@ void tst_QQuickGridView::populateTransitions()
QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), 0);
QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 18);
} else {
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QCOMPARE(gridview->property("countPopulateTransitions").toInt(), 0);
QCOMPARE(gridview->property("countAddTransitions").toInt(), 0);
}
@@ -4598,7 +4636,7 @@ void tst_QQuickGridView::populateTransitions()
QTRY_COMPARE(item->x(), (i%3)*80.0);
QTRY_COMPARE(item->y(), (i/3)*60.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -4622,7 +4660,7 @@ void tst_QQuickGridView::populateTransitions()
for (int i = 0; i < 30; i++)
model.addItem("item" + QString::number(i), "");
window->rootContext()->setContextProperty("testModel", &model);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 18 : 0);
QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 0);
@@ -4634,7 +4672,7 @@ void tst_QQuickGridView::populateTransitions()
QTRY_COMPARE(item->x(), (i%3)*80.0);
QTRY_COMPARE(item->y(), (i/3)*60.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -4652,7 +4690,7 @@ void tst_QQuickGridView::populateTransitions()
QTRY_COMPARE(item->x(), (i%3)*80.0);
QTRY_COMPARE(item->y(), (i/3)*60.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -4707,14 +4745,14 @@ void tst_QQuickGridView::addTransitions()
window->show();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
if (contentYRowOffset != 0) {
gridview->setContentY(contentYRowOffset * 60.0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
}
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
@@ -4788,7 +4826,7 @@ void tst_QQuickGridView::addTransitions()
QCOMPARE(item->x(), (i%3)*80.0);
QCOMPARE(item->y(), (i/3)*60.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), model.name(i));
}
@@ -4912,14 +4950,14 @@ void tst_QQuickGridView::moveTransitions()
window->show();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickText *name;
if (contentYRowOffset != 0) {
gridview->setContentY(contentYRowOffset * 60.0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
}
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
@@ -4986,7 +5024,7 @@ void tst_QQuickGridView::moveTransitions()
QCOMPARE(item->x(), (i%3)*80.0);
QCOMPARE(item->y(), (i/3)*60.0 + pixelOffset);
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -5157,14 +5195,14 @@ void tst_QQuickGridView::removeTransitions()
window->show();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
if (contentYRowOffset != 0) {
gridview->setContentY(contentYRowOffset * 60.0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
}
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
@@ -5240,7 +5278,7 @@ void tst_QQuickGridView::removeTransitions()
QCOMPARE(item->x(), (i%3)*80.0);
QCOMPARE(item->y(), gridview->contentY() + ((i-firstVisibleIndex)/3) * 60.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -5375,10 +5413,10 @@ void tst_QQuickGridView::displacedTransitions()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
gridview->setProperty("displaceTransitionsDone", false);
@@ -5399,7 +5437,7 @@ void tst_QQuickGridView::displacedTransitions()
break;
case ListChange::Moved:
model.moveItems(change.index, change.to, change.count);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
break;
case ListChange::SetCurrent:
case ListChange::SetContentY:
@@ -5459,7 +5497,7 @@ void tst_QQuickGridView::displacedTransitions()
QCOMPARE(item->x(), (i%3)*80.0);
QCOMPARE(item->y(), (i/3)*60.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -5594,14 +5632,14 @@ void tst_QQuickGridView::multipleTransitions()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
if (contentY != 0) {
gridview->setContentY(contentY);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
}
int timeBetweenActions = window->rootObject()->property("timeBetweenActions").toInt();
@@ -5638,7 +5676,7 @@ void tst_QQuickGridView::multipleTransitions()
case ListChange::Moved:
model.moveItems(changes[i].index, changes[i].to, changes[i].count);
gridview->forceLayout();
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
if (i == changes.count() - 1) {
QTRY_VERIFY(!gridview->property("runningMoveTargets").toBool());
QTRY_VERIFY(!gridview->property("runningMoveDisplaced").toBool());
@@ -5648,12 +5686,12 @@ void tst_QQuickGridView::multipleTransitions()
break;
case ListChange::SetCurrent:
gridview->setCurrentIndex(changes[i].index);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
gridview->forceLayout();
break;
case ListChange::SetContentY:
gridview->setContentY(changes[i].pos);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
gridview->forceLayout();
break;
case ListChange::Polish:
@@ -5681,7 +5719,7 @@ void tst_QQuickGridView::multipleTransitions()
QTRY_COMPARE(item->x(), (i%3)*80.0);
QTRY_COMPARE(item->y(), (i/3)*60.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -5764,10 +5802,10 @@ void tst_QQuickGridView::multipleDisplaced()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
model.moveItems(12, 8, 1);
QTest::qWait(window->rootObject()->property("duration").toInt() / 2);
@@ -5788,13 +5826,72 @@ void tst_QQuickGridView::multipleDisplaced()
QTRY_COMPARE(item->x(), (i%3)*80.0);
QTRY_COMPARE(item->y(), (i/3)*60.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
delete window;
}
+void tst_QQuickGridView::regression_QTBUG_57225()
+{
+ QFETCH(int, initialCount);
+ QFETCH(int, removeIndex);
+ QFETCH(int, removeCount);
+ QFETCH(int, expectedDisplaceTransitions);
+
+ // deleting all visible items should not cause a repositioning of said items.
+
+ QaimModel model;
+ for (int i = 0; i < initialCount; i++)
+ model.addItem("Original item" + QString::number(i), "");
+
+ QQuickView *window = createView();
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ window->setSource(testFileUrl("qtbug57225.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
+ QVERIFY(gridview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(gridview));
+
+ model.removeItems(removeIndex, removeCount);
+ QTRY_VERIFY(gridview->property("animationDone").toBool());
+
+ // verify that none of the removed items has moved to a negative position
+ QPoint minimumPosition = gridview->property("minimumPosition").toPoint();
+ QVERIFY(minimumPosition.x() >= 0);
+ QVERIFY(minimumPosition.y() >= 0);
+
+ // wait some more time to let the displaced transition happen
+ QTest::qWait(window->rootObject()->property("duration").toInt());
+ QTRY_VERIFY2(gridview->property("displaceTransitionsDone").toInt() >= expectedDisplaceTransitions,
+ QByteArray::number(gridview->property("displaceTransitionsDone").toInt()).constData());
+
+ delete window;
+}
+
+void tst_QQuickGridView::regression_QTBUG_57225_data()
+{
+ QTest::addColumn<int>("initialCount");
+ QTest::addColumn<int>("removeIndex");
+ QTest::addColumn<int>("removeCount");
+ QTest::addColumn<int>("expectedDisplaceTransitions");
+
+ // no displace transitions should happen
+ QTest::newRow("remove all visible items") <<
+ 20 << 0 << 8 << 0;
+
+ // check that the removal animation is performed
+ QTest::newRow("remove items in between") <<
+ 20 << 1 << 2 << 3;
+
+ QTest::newRow("remove items in between - 2") <<
+ 20 << 2 << 3 << 1;
+}
+
void tst_QQuickGridView::cacheBuffer()
{
QQuickView *window = createView();
@@ -5809,11 +5906,11 @@ void tst_QQuickGridView::cacheBuffer()
qApp->processEvents();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QVERIFY(gridview != 0);
+ QVERIFY(gridview != nullptr);
QQuickItem *contentItem = gridview->contentItem();
- QVERIFY(contentItem != 0);
- QVERIFY(gridview->delegate() != 0);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(gridview->delegate() != nullptr);
QVERIFY(gridview->model() != 0);
// Confirm items positioned correctly
@@ -5832,8 +5929,8 @@ void tst_QQuickGridView::cacheBuffer()
// items will be created one at a time
for (int i = itemCount; i < qMin(itemCount+9,model.count()); ++i) {
- QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
- QQuickItem *item = 0;
+ QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == nullptr);
+ QQuickItem *item = nullptr;
while (!item) {
bool b = false;
controller.incubateWhile(&b);
@@ -5867,11 +5964,11 @@ void tst_QQuickGridView::cacheBuffer()
QTRY_COMPARE(item->y(), (i/3)*60.0);
}
- QVERIFY(findItem<QQuickItem>(gridview, "wrapper", 34) == 0);
+ QVERIFY(findItem<QQuickItem>(gridview, "wrapper", 34) == nullptr);
// ensure buffered items are created
for (int i = 34; i < qMin(44,model.count()); ++i) {
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
while (!item) {
qGuiApp->processEvents(); // allow refill to happen
bool b = false;
@@ -5900,7 +5997,7 @@ void tst_QQuickGridView::asynchronous()
QQuickItem *rootObject = qobject_cast<QQuickItem*>(window->rootObject());
QVERIFY(rootObject);
- QQuickGridView *gridview = 0;
+ QQuickGridView *gridview = nullptr;
while (!gridview) {
bool b = false;
controller.incubateWhile(&b);
@@ -5909,8 +6006,8 @@ void tst_QQuickGridView::asynchronous()
// items will be created one at a time
for (int i = 0; i < 12; ++i) {
- QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
- QQuickItem *item = 0;
+ QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == nullptr);
+ QQuickItem *item = nullptr;
while (!item) {
bool b = false;
controller.incubateWhile(&b);
@@ -5941,7 +6038,7 @@ void tst_QQuickGridView::unrequestedVisibility()
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setGeometry(0,0,240,320);
QQmlContext *ctxt = window->rootContext();
@@ -5955,16 +6052,16 @@ void tst_QQuickGridView::unrequestedVisibility()
qApp->processEvents();
QQuickGridView *leftview = findItem<QQuickGridView>(window->rootObject(), "leftGrid");
- QTRY_VERIFY(leftview != 0);
+ QTRY_VERIFY(leftview != nullptr);
QQuickGridView *rightview = findItem<QQuickGridView>(window->rootObject(), "rightGrid");
- QTRY_VERIFY(rightview != 0);
+ QTRY_VERIFY(rightview != nullptr);
QQuickItem *leftContent = leftview->contentItem();
- QTRY_VERIFY(leftContent != 0);
+ QTRY_VERIFY(leftContent != nullptr);
QQuickItem *rightContent = rightview->contentItem();
- QTRY_VERIFY(rightContent != 0);
+ QTRY_VERIFY(rightContent != nullptr);
rightview->setCurrentIndex(12);
@@ -6031,7 +6128,7 @@ void tst_QQuickGridView::unrequestedVisibility()
// move a non-visible item into view
model.moveItems(10, 9, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
QTRY_VERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QCOMPARE(delegateVisible(item), false);
@@ -6054,7 +6151,7 @@ void tst_QQuickGridView::unrequestedVisibility()
// move a visible item out of view
model.moveItems(5, 3, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
QCOMPARE(delegateVisible(item), false);
@@ -6067,7 +6164,7 @@ void tst_QQuickGridView::unrequestedVisibility()
// move a non-visible item into view
model.moveItems(3, 5, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
QCOMPARE(delegateVisible(item), false);
@@ -6080,7 +6177,7 @@ void tst_QQuickGridView::unrequestedVisibility()
// move a visible item out of view
model.moveItems(9, 10, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
QCOMPARE(delegateVisible(item), false);
@@ -6093,7 +6190,7 @@ void tst_QQuickGridView::unrequestedVisibility()
// move a non-visible item into view
model.moveItems(10, 9, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
QCOMPARE(delegateVisible(item), false);
@@ -6379,10 +6476,10 @@ void tst_QQuickGridView::displayMargin()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickGridView *gridview = window->rootObject()->findChild<QQuickGridView*>();
- QVERIFY(gridview != 0);
+ QVERIFY(gridview != nullptr);
QQuickItem *content = gridview->contentItem();
- QVERIFY(content != 0);
+ QVERIFY(content != nullptr);
QQuickItem *item0;
QQuickItem *item97;
@@ -6395,7 +6492,7 @@ void tst_QQuickGridView::displayMargin()
QCOMPARE(delegateVisible(item97), true);
// GridView staggers item creation, so the 118th item should be outside the end margin.
- QVERIFY(findItem<QQuickItem>(content, "delegate", 117) == 0);
+ QVERIFY(findItem<QQuickItem>(content, "delegate", 117) == nullptr);
// the first delegate should still be within the begin margin
gridview->positionViewAtIndex(20, QQuickGridView::Beginning);
@@ -6418,13 +6515,13 @@ void tst_QQuickGridView::negativeDisplayMargin()
QQuickItem *listview = window->rootObject();
QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid");
- QVERIFY(gridview != 0);
+ QVERIFY(gridview != nullptr);
QTRY_COMPARE(gridview->property("createdItems").toInt(), 11);
QCOMPARE(gridview->property("destroyedItem").toInt(), 0);
QQuickItem *content = gridview->contentItem();
- QVERIFY(content != 0);
+ QVERIFY(content != nullptr);
QVERIFY(item = findItem<QQuickItem>(content, "delegate", 0));
QCOMPARE(delegateVisible(item), true);
@@ -6523,7 +6620,7 @@ void tst_QQuickGridView::contentHeightWithDelayRemove()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickGridView *gridview = window->rootObject()->findChild<QQuickGridView*>();
- QTRY_VERIFY(gridview != 0);
+ QTRY_VERIFY(gridview != nullptr);
const int initialCount(gridview->count());
const int eventualCount(initialCount + countDelta);
@@ -6554,7 +6651,7 @@ void tst_QQuickGridView::QTBUG_45640()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject());
- QVERIFY(gridview != 0);
+ QVERIFY(gridview != nullptr);
QCOMPARE(gridview->contentY(), qreal(-50.0));
@@ -6565,6 +6662,36 @@ void tst_QQuickGridView::QTBUG_45640()
delete window;
}
+void tst_QQuickGridView::QTBUG_49218()
+{
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("qtbug49218.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
+ QQuickGridView *gridview = qobject_cast<QQuickGridView *>(rootItem->childItems().first());
+ QVERIFY(gridview != nullptr);
+
+ auto processEventsAndForceLayout = [&gridview] () {
+ for (int pass = 0; pass < 2; ++pass) {
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ gridview->forceLayout();
+ }
+ };
+ QMetaObject::invokeMethod(rootItem, "scrollToTop");
+ processEventsAndForceLayout();
+ QMetaObject::invokeMethod(rootItem, "changeModel");
+ processEventsAndForceLayout();
+ QMetaObject::invokeMethod(rootItem, "changeModel");
+ processEventsAndForceLayout();
+ QMetaObject::invokeMethod(rootItem, "scrollToTop");
+ processEventsAndForceLayout();
+
+ QCOMPARE(gridview->indexAt(gridview->cellWidth() - 10, gridview->cellHeight() - 10), 0);
+ delete window;
+}
+
void tst_QQuickGridView::keyNavigationEnabled()
{
QScopedPointer<QQuickView> window(createView());
@@ -6643,11 +6770,11 @@ void tst_QQuickGridView::QTBUG_48870_fastModelUpdates()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickGridView *view = findItem<QQuickGridView>(window->rootObject(), "view");
- QTRY_VERIFY(view != 0);
+ QTRY_VERIFY(view != nullptr);
QQuickItemViewPrivate *priv = QQuickItemViewPrivate::get(view);
bool nonUnique;
- FxViewItem *item = Q_NULLPTR;
+ FxViewItem *item = nullptr;
int expectedIdx;
QVERIFY(testVisibleItems(priv, &nonUnique, &item, &expectedIdx));
@@ -6666,6 +6793,18 @@ void tst_QQuickGridView::QTBUG_48870_fastModelUpdates()
}
}
+void tst_QQuickGridView::releaseItems()
+{
+ QScopedPointer<QQuickView> view(createView());
+ view->setSource(testFileUrl("releaseItems.qml"));
+
+ QQuickGridView *gridview = qobject_cast<QQuickGridView *>(view->rootObject());
+ QVERIFY(gridview);
+
+ // don't crash (QTBUG-61294)
+ gridview->setModel(123);
+}
+
QTEST_MAIN(tst_QQuickGridView)
#include "tst_qquickgridview.moc"
diff --git a/tests/auto/quick/qquickimage/data/car.ktx b/tests/auto/quick/qquickimage/data/car.ktx
new file mode 100644
index 0000000000..2aefdd306b
--- /dev/null
+++ b/tests/auto/quick/qquickimage/data/car.ktx
Binary files differ
diff --git a/tests/auto/quick/qquickimage/data/logo.pkm b/tests/auto/quick/qquickimage/data/logo.pkm
new file mode 100644
index 0000000000..c0987c5c36
--- /dev/null
+++ b/tests/auto/quick/qquickimage/data/logo.pkm
Binary files differ
diff --git a/tests/auto/quick/qquickimage/data/pattern.pkm b/tests/auto/quick/qquickimage/data/pattern.pkm
new file mode 100644
index 0000000000..d986e89b2d
--- /dev/null
+++ b/tests/auto/quick/qquickimage/data/pattern.pkm
Binary files differ
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index 36d99ad48d..d1f46a3912 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -62,6 +62,7 @@ public:
tst_qquickimage();
private slots:
+ void initTestCase();
void cleanup();
void noSource();
void imageSource();
@@ -97,12 +98,22 @@ private slots:
private:
QQmlEngine engine;
+ QSGRendererInterface::GraphicsApi graphicsApi = QSGRendererInterface::Unknown;
};
tst_qquickimage::tst_qquickimage()
{
}
+void tst_qquickimage::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ QScopedPointer<QQuickView> window(new QQuickView(0));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ graphicsApi = window->rendererInterface()->graphicsApi();
+}
+
void tst_qquickimage::cleanup()
{
QQuickWindow window;
@@ -116,7 +127,7 @@ void tst_qquickimage::noSource()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->source(), QUrl());
QCOMPARE(obj->status(), QQuickImage::Null);
QCOMPARE(obj->width(), 0.);
@@ -150,8 +161,27 @@ void tst_qquickimage::imageSource_data()
QTest::newRow("remote svg") << "/heart.svg" << 595.0 << 841.0 << true << false << false << "";
if (QImageReader::supportedImageFormats().contains("svgz"))
QTest::newRow("remote svgz") << "/heart.svgz" << 595.0 << 841.0 << true << false << false << "";
+ if (graphicsApi == QSGRendererInterface::OpenGL) {
+ QTest::newRow("texturefile pkm format") << testFileUrl("logo.pkm").toString() << 256.0 << 256.0 << false << false << true << "";
+ QTest::newRow("texturefile ktx format") << testFileUrl("car.ktx").toString() << 146.0 << 80.0 << false << false << true << "";
+ QTest::newRow("texturefile async") << testFileUrl("logo.pkm").toString() << 256.0 << 256.0 << false << true << true << "";
+ }
QTest::newRow("remote not found") << "/no-such-file.png" << 0.0 << 0.0 << true
<< false << true << "<Unknown File>:2:1: QML Image: Error transferring {{ServerBaseUrl}}/no-such-file.png - server replied: Not found";
+ QTest::newRow("extless") << testFileUrl("colors").toString() << 120.0 << 120.0 << false << false << true << "";
+ QTest::newRow("extless no cache") << testFileUrl("colors").toString() << 120.0 << 120.0 << false << false << false << "";
+ QTest::newRow("extless async") << testFileUrl("colors1").toString() << 120.0 << 120.0 << false << true << true << "";
+ QTest::newRow("extless not found") << testFileUrl("no-such-file").toString() << 0.0 << 0.0 << false
+ << false << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file").toString();
+ // Test that texture file is preferred over image file, when supported.
+ // Since pattern.pkm has different size than pattern.png, these tests verify that the right file has been loaded
+ if (graphicsApi == QSGRendererInterface::OpenGL) {
+ QTest::newRow("extless prefer-tex") << testFileUrl("pattern").toString() << 64.0 << 64.0 << false << false << true << "";
+ QTest::newRow("extless prefer-tex async") << testFileUrl("pattern").toString() << 64.0 << 64.0 << false << true << true << "";
+ } else {
+ QTest::newRow("extless ignore-tex") << testFileUrl("pattern").toString() << 200.0 << 200.0 << false << false << true << "";
+ QTest::newRow("extless ignore-tex async") << testFileUrl("pattern").toString() << 200.0 << 200.0 << false << true << true << "";
+ }
}
@@ -195,7 +225,7 @@ void tst_qquickimage::imageSource()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
if (async)
QVERIFY(obj->asynchronous());
@@ -233,7 +263,7 @@ void tst_qquickimage::clearSource()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickImage::Ready);
QCOMPARE(obj->width(), 120.);
QCOMPARE(obj->height(), 120.);
@@ -255,7 +285,7 @@ void tst_qquickimage::resized()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 300.);
QCOMPARE(obj->height(), 300.);
QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
@@ -265,13 +295,13 @@ void tst_qquickimage::resized()
void tst_qquickimage::preserveAspectRatio()
{
- QScopedPointer<QQuickView> window(new QQuickView(0));
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
window->setSource(testFileUrl("aspectratio.qml"));
QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject());
- QVERIFY(image != 0);
+ QVERIFY(image != nullptr);
image->setWidth(80.0);
QCOMPARE(image->width(), 80.);
QCOMPARE(image->height(), 80.);
@@ -279,7 +309,7 @@ void tst_qquickimage::preserveAspectRatio()
window->setSource(testFileUrl("aspectratio.qml"));
image = qobject_cast<QQuickImage*>(window->rootObject());
image->setHeight(60.0);
- QVERIFY(image != 0);
+ QVERIFY(image != nullptr);
QCOMPARE(image->height(), 60.);
QCOMPARE(image->width(), 60.);
}
@@ -290,7 +320,7 @@ void tst_qquickimage::smooth()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 300.);
QCOMPARE(obj->height(), 300.);
QCOMPARE(obj->smooth(), true);
@@ -301,6 +331,10 @@ void tst_qquickimage::smooth()
void tst_qquickimage::mirror()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QMap<QQuickImage::FillMode, QImage> screenshots;
QList<QQuickImage::FillMode> fillModes;
fillModes << QQuickImage::Stretch << QQuickImage::PreserveAspectFit << QQuickImage::PreserveAspectCrop
@@ -315,7 +349,7 @@ void tst_qquickimage::mirror()
window->setSource(testFileUrl("mirror.qml"));
QQuickImage *obj = window->rootObject()->findChild<QQuickImage*>("image");
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
obj->setFillMode(fillMode);
obj->setProperty("mirror", true);
@@ -399,13 +433,24 @@ void tst_qquickimage::svg()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
- QCOMPARE(obj->width(), 212.0);
+ QVERIFY(obj != nullptr);
+ QCOMPARE(obj->width(), 300.0);
QCOMPARE(obj->height(), 300.0);
obj->setSourceSize(QSize(200,200));
- QCOMPARE(obj->width(), 141.0);
+ QCOMPARE(obj->width(), 200.0);
QCOMPARE(obj->height(), 200.0);
+ obj->setSourceSize(QSize(100,0));
+ QCOMPARE(obj->width(), 100.0);
+ // Due to aspect ratio calculations we can't get a precise
+ // check for all setups, so we allow a small margin of error
+ QVERIFY(qAbs(obj->height() - 141) < 1);
+
+ // Setting it to a size bigger than the actual file, SVG formats
+ // can scale up although other image formats cannot
+ obj->setSourceSize(QSize(800,0));
+ QCOMPARE(obj->width(), 800.0);
+ QVERIFY(qAbs(obj->height() - 1131) < 1);
delete obj;
}
@@ -469,7 +514,7 @@ void tst_qquickimage::geometry()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), itemWidth);
QCOMPARE(obj->paintedWidth(), paintedWidth);
@@ -492,7 +537,7 @@ void tst_qquickimage::big()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 100.0);
QCOMPARE(obj->height(), 256.0);
@@ -501,6 +546,10 @@ void tst_qquickimage::big()
void tst_qquickimage::tiling_QTBUG_6716()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QFETCH(QString, source);
QQuickView view(testFileUrl(source));
@@ -509,7 +558,7 @@ void tst_qquickimage::tiling_QTBUG_6716()
QQuickImage *tiling = findItem<QQuickImage>(view.rootObject(), "tiling");
- QVERIFY(tiling != 0);
+ QVERIFY(tiling != nullptr);
QImage img = view.grabWindow();
for (int x = 0; x < tiling->width(); ++x) {
for (int y = 0; y < tiling->height(); ++y) {
@@ -540,7 +589,7 @@ void tst_qquickimage::noLoading()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickImage::Ready);
QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(QUrl)));
@@ -587,7 +636,7 @@ void tst_qquickimage::paintedWidthHeight()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 200.0);
QCOMPARE(obj->height(), 25.0);
QCOMPARE(obj->paintedWidth(), 25.0);
@@ -602,7 +651,7 @@ void tst_qquickimage::paintedWidthHeight()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 26.0);
QCOMPARE(obj->height(), 175.0);
QCOMPARE(obj->paintedWidth(), 26.0);
@@ -623,7 +672,7 @@ void tst_qquickimage::sourceSize_QTBUG_14303()
QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged()));
- QTRY_VERIFY(obj != 0);
+ QTRY_VERIFY(obj != nullptr);
QTRY_COMPARE(obj->status(), QQuickImage::Ready);
QTRY_COMPARE(obj->sourceSize().width(), 200);
@@ -645,7 +694,7 @@ void tst_qquickimage::sourceSize_QTBUG_14303()
void tst_qquickimage::sourceSize_QTBUG_16389()
{
- QScopedPointer<QQuickView> window(new QQuickView(0));
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
window->setSource(testFileUrl("qtbug_16389.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -669,7 +718,7 @@ void tst_qquickimage::sourceSize_QTBUG_16389()
// QTBUG-15690
void tst_qquickimage::nullPixmapPaint()
{
- QScopedPointer<QQuickView> window(new QQuickView(0));
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
window->setSource(testFileUrl("nullpixmap.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -679,7 +728,7 @@ void tst_qquickimage::nullPixmapPaint()
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject());
- QTRY_VERIFY(image != 0);
+ QTRY_VERIFY(image != nullptr);
image->setSource(server.url("/no-such-file.png"));
QQmlTestMessageHandler messageHandler;
@@ -709,7 +758,7 @@ void tst_qquickimage::imageCrash_QTBUG_22125()
// shouldn't crash when deleting cancelled QQmlPixmapReplys.
server.sendDelayedItem();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
}
@@ -742,7 +791,7 @@ void tst_qquickimage::sourceSize()
QFETCH(qreal, implicitWidth);
QFETCH(qreal, implicitHeight);
- QScopedPointer<QQuickView> window(new QQuickView(0));
+ QScopedPointer<QQuickView> window(new QQuickView(nullptr));
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("srcWidth", sourceWidth);
ctxt->setContextProperty("srcHeight", sourceHeight);
@@ -773,7 +822,7 @@ void tst_qquickimage::sourceSizeChanges()
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("srcImage", "");
QQuickImage *img = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(img != 0);
+ QVERIFY(img != nullptr);
QSignalSpy sourceSizeSpy(img, SIGNAL(sourceSizeChanged()));
@@ -839,7 +888,7 @@ void tst_qquickimage::progressAndStatusChanges()
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickImage::Ready);
QTRY_COMPARE(obj->progress(), 1.0);
@@ -956,7 +1005,7 @@ void tst_qquickimage::highdpi()
ctxt->setContextProperty("srcImage", testFileUrl("heart-highdpi@2x.png"));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->width(), 150.0);
QCOMPARE(obj->height(), 150.0);
@@ -1034,6 +1083,10 @@ void tst_qquickimage::highDpiFillModesAndSizes()
void tst_qquickimage::hugeImages()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QQuickView view;
view.setSource(testFileUrl("hugeImages.qml"));
view.setGeometry(0, 0, 200, 200);
diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
index 98f3972cef..4b75a7e008 100644
--- a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
+++ b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
@@ -65,6 +65,7 @@ private slots:
void threadTest();
void asyncTextureTest();
+ void instantAsyncTextureTest();
private:
QString newImageFileName() const;
@@ -76,7 +77,7 @@ private:
class TestQImageProvider : public QQuickImageProvider
{
public:
- TestQImageProvider(bool *deleteWatch = 0, bool forceAsync = false)
+ TestQImageProvider(bool *deleteWatch = nullptr, bool forceAsync = false)
: QQuickImageProvider(Image, (forceAsync ? ForceAsynchronousImageLoading : Flags()))
, deleteWatch(deleteWatch)
{
@@ -114,7 +115,7 @@ Q_DECLARE_METATYPE(TestQImageProvider*);
class TestQPixmapProvider : public QQuickImageProvider
{
public:
- TestQPixmapProvider(bool *deleteWatch = 0)
+ TestQPixmapProvider(bool *deleteWatch = nullptr)
: QQuickImageProvider(Pixmap), deleteWatch(deleteWatch)
{
}
@@ -217,7 +218,7 @@ void tst_qquickimageprovider::runTest(bool async, QQuickImageProvider *provider)
QQmlEngine engine;
engine.addImageProvider("test", provider);
- QVERIFY(engine.imageProvider("test") != 0);
+ QVERIFY(engine.imageProvider("test") != nullptr);
QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; "
+ (async ? "asynchronous: true; " : "")
@@ -225,7 +226,7 @@ void tst_qquickimageprovider::runTest(bool async, QQuickImageProvider *provider)
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
// From this point on, treat forced async providers as async behaviour-wise
if (engine.imageProvider(QUrl(source).host()) == provider)
@@ -314,14 +315,14 @@ void tst_qquickimageprovider::requestPixmap_async()
QQuickImageProvider *provider = new TestQPixmapProvider();
engine.addImageProvider("test", provider);
- QVERIFY(engine.imageProvider("test") != 0);
+ QVERIFY(engine.imageProvider("test") != nullptr);
// pixmaps are loaded synchronously regardless of 'asynchronous' value
QString componentStr = "import QtQuick 2.0\nImage { asynchronous: true; source: \"image://test/pixmap-async-test.png\" }";
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
delete obj;
}
@@ -341,14 +342,14 @@ void tst_qquickimageprovider::removeProvider()
QQmlEngine engine;
engine.addImageProvider("test", provider);
- QVERIFY(engine.imageProvider("test") != 0);
+ QVERIFY(engine.imageProvider("test") != nullptr);
// add provider, confirm it works
QString componentStr = "import QtQuick 2.0\nImage { source: \"" + newImageFileName() + "\" }";
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickImage::Ready);
@@ -384,7 +385,7 @@ void tst_qquickimageprovider::imageProviderId()
TestQImageProvider *provider = new TestQImageProvider(&deleteWatch);
engine.addImageProvider(providerId, provider);
- QVERIFY(engine.imageProvider(providerId) != 0);
+ QVERIFY(engine.imageProvider(providerId) != nullptr);
engine.removeImageProvider(providerId);
QVERIFY(deleteWatch);
@@ -393,7 +394,7 @@ void tst_qquickimageprovider::imageProviderId()
class TestThreadProvider : public QQuickImageProvider
{
public:
- TestThreadProvider() : QQuickImageProvider(Image), ok(false) {}
+ TestThreadProvider() : QQuickImageProvider(Image) {}
~TestThreadProvider() {}
@@ -417,7 +418,7 @@ class TestThreadProvider : public QQuickImageProvider
QWaitCondition cond;
QMutex mutex;
- bool ok;
+ bool ok = false;
};
@@ -428,7 +429,7 @@ void tst_qquickimageprovider::threadTest()
TestThreadProvider *provider = new TestThreadProvider;
engine.addImageProvider("test_thread", provider);
- QVERIFY(engine.imageProvider("test_thread") != 0);
+ QVERIFY(engine.imageProvider("test_thread") != nullptr);
QString componentStr = "import QtQuick 2.0\nItem { \n"
"Image { source: \"image://test_thread/blue\"; asynchronous: true; }\n"
@@ -440,7 +441,7 @@ void tst_qquickimageprovider::threadTest()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QObject *obj = component.create();
//MUST not deadlock
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
QCOMPARE(images.count(), 4);
QTest::qWait(100);
@@ -459,7 +460,7 @@ class TestImageResponse : public QQuickImageResponse, public QRunnable
{
public:
TestImageResponse(QMutex *lock, QWaitCondition *condition, bool *ok, const QString &id, const QSize &requestedSize)
- : m_lock(lock), m_condition(condition), m_ok(ok), m_id(id), m_requestedSize(requestedSize), m_texture(0)
+ : m_lock(lock), m_condition(condition), m_ok(ok), m_id(id), m_requestedSize(requestedSize), m_texture(nullptr)
{
setAutoDelete(false);
}
@@ -495,7 +496,7 @@ class TestImageResponse : public QQuickImageResponse, public QRunnable
class TestAsyncProvider : public QQuickAsyncImageProvider
{
public:
- TestAsyncProvider() : ok(false)
+ TestAsyncProvider()
{
pool.setMaxThreadCount(4);
}
@@ -512,7 +513,7 @@ class TestAsyncProvider : public QQuickAsyncImageProvider
QThreadPool pool;
QMutex lock;
QWaitCondition condition;
- bool ok;
+ bool ok = false;
};
@@ -523,7 +524,7 @@ void tst_qquickimageprovider::asyncTextureTest()
TestAsyncProvider *provider = new TestAsyncProvider;
engine.addImageProvider("test_async", provider);
- QVERIFY(engine.imageProvider("test_async") != 0);
+ QVERIFY(engine.imageProvider("test_async") != nullptr);
QString componentStr = "import QtQuick 2.0\nItem { \n"
"Image { source: \"image://test_async/blue\"; }\n"
@@ -535,7 +536,7 @@ void tst_qquickimageprovider::asyncTextureTest()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QObject *obj = component.create();
//MUST not deadlock
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
QCOMPARE(images.count(), 4);
@@ -550,6 +551,70 @@ void tst_qquickimageprovider::asyncTextureTest()
}
}
+class InstantAsyncImageResponse : public QQuickImageResponse
+{
+ public:
+ InstantAsyncImageResponse(const QString &id, const QSize &requestedSize)
+ {
+ QImage image(50, 50, QImage::Format_RGB32);
+ image.fill(QColor(id).rgb());
+ if (requestedSize.isValid())
+ image = image.scaled(requestedSize);
+ m_texture = QQuickTextureFactory::textureFactoryForImage(image);
+ emit finished();
+ }
+
+ QQuickTextureFactory *textureFactory() const
+ {
+ return m_texture;
+ }
+
+ QQuickTextureFactory *m_texture;
+};
+
+class InstancAsyncProvider : public QQuickAsyncImageProvider
+{
+ public:
+ InstancAsyncProvider()
+ {
+ }
+
+ ~InstancAsyncProvider() {}
+
+ QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize)
+ {
+ return new InstantAsyncImageResponse(id, requestedSize);
+ }
+};
+
+void tst_qquickimageprovider::instantAsyncTextureTest()
+{
+ QQmlEngine engine;
+
+ InstancAsyncProvider *provider = new InstancAsyncProvider;
+
+ engine.addImageProvider("test_instantasync", provider);
+ QVERIFY(engine.imageProvider("test_instantasync") != nullptr);
+
+ QString componentStr = "import QtQuick 2.0\nItem { \n"
+ "Image { source: \"image://test_instantasync/blue\"; }\n"
+ "Image { source: \"image://test_instantasync/red\"; }\n"
+ "Image { source: \"image://test_instantasync/green\"; }\n"
+ "Image { source: \"image://test_instantasync/yellow\"; }\n"
+ " }";
+ QQmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QScopedPointer<QObject> obj(component.create());
+
+ QVERIFY(!obj.isNull());
+ const QList<QQuickImage *> images = obj->findChildren<QQuickImage *>();
+ QCOMPARE(images.count(), 4);
+
+ for (QQuickImage *img: images) {
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ }
+}
+
QTEST_MAIN(tst_qquickimageprovider)
diff --git a/tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml b/tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml
new file mode 100644
index 0000000000..eeecd48cb2
--- /dev/null
+++ b/tests/auto/quick/qquickitem/data/mainWindowQtBug60123.qml
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 400
+ height: 200
+ color: "white"
+ property string lastEvent: ""
+
+ Rectangle {
+ id: buttonRect
+ width: 50
+ height: 50
+ color: "black"
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ lastEvent = "pressed"
+ buttonRect.color = "yellow"
+ }
+ onReleased: {
+ lastEvent = "released"
+ buttonRect.color = "black"
+ }
+ onCanceled: {
+ lastEvent = "canceled"
+ buttonRect.color = "green"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem/qquickitem.pro b/tests/auto/quick/qquickitem/qquickitem.pro
index 9aca5926f2..003981d4de 100644
--- a/tests/auto/quick/qquickitem/qquickitem.pro
+++ b/tests/auto/quick/qquickitem/qquickitem.pro
@@ -11,3 +11,8 @@ TESTDATA = data/*
QT += core-private gui-private qml-private quick-private testlib
+qtHaveModule(widgets): {
+ DEFINES += TEST_QTBUG_60123
+ QT += widgets
+}
+
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 10a3a0bfa8..7e132f97b6 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -41,15 +41,25 @@
#include "../shared/viewtestutil.h"
#include <QSignalSpy>
+#ifdef TEST_QTBUG_60123
+#include <QWidget>
+#include <QMainWindow>
+#endif
+
class TestItem : public QQuickItem
{
Q_OBJECT
public:
- TestItem(QQuickItem *parent = 0)
+ TestItem(QQuickItem *parent = nullptr)
: QQuickItem(parent), focused(false), pressCount(0), releaseCount(0)
, wheelCount(0), acceptIncomingTouchEvents(true)
, touchEventReached(false), timestamp(0)
- , lastWheelEventPos(0, 0), lastWheelEventGlobalPos(0, 0) {}
+ , lastWheelEventPos(0, 0), lastWheelEventGlobalPos(0, 0)
+ {
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ setAcceptTouchEvents(true);
+#endif
+ }
bool focused;
int pressCount;
@@ -95,7 +105,7 @@ class TestPolishItem : public QQuickItem
{
Q_OBJECT
public:
- TestPolishItem(QQuickItem *parent = 0)
+ TestPolishItem(QQuickItem *parent = nullptr)
: QQuickItem(parent), wasPolished(false) {
}
@@ -117,7 +127,7 @@ class TestFocusScope : public QQuickFocusScope
{
Q_OBJECT
public:
- TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {}
+ TestFocusScope(QQuickItem *parent = nullptr) : QQuickFocusScope(parent), focused(false) {}
bool focused;
protected:
@@ -183,18 +193,22 @@ private slots:
void shortcutOverride();
+#ifdef TEST_QTBUG_60123
+ void qtBug60123();
+#endif
+
private:
enum PaintOrderOp {
NoOp, Append, Remove, StackBefore, StackAfter, SetZ
};
- void ensureFocus(QWindow *w) {
+ bool ensureFocus(QWindow *w) {
if (w->width() <=0 || w->height() <= 0)
w->setGeometry(100, 100, 400, 300);
w->show();
w->requestActivate();
- QTest::qWaitForWindowActive(w);
+ return QTest::qWaitForWindowActive(w);
}
};
@@ -250,7 +264,7 @@ struct FocusData {
};
struct FocusState : public QHash<QQuickItem *, FocusData>
{
- FocusState() : activeFocusItem(0) {}
+ FocusState() : activeFocusItem(nullptr) {}
FocusState &operator<<(QQuickItem *item) {
insert(item, FocusData());
return *this;
@@ -285,7 +299,7 @@ struct FocusState : public QHash<QQuickItem *, FocusData>
void tst_qquickitem::simpleFocus()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
@@ -324,7 +338,7 @@ void tst_qquickitem::simpleFocus()
l1c3->setFocus(false);
focusState[l1c3].set(false, false);
- focusState.active(0);
+ focusState.active(nullptr);
FVERIFY();
l2c1->setFocus(true);
@@ -337,7 +351,7 @@ void tst_qquickitem::simpleFocus()
void tst_qquickitem::scopedFocus()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *l1c1 = new TestItem(window.contentItem());
@@ -417,7 +431,7 @@ void tst_qquickitem::addedToWindow()
{
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *item = new TestItem;
@@ -437,7 +451,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *item = new TestItem(window.contentItem());
@@ -466,7 +480,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *tree = new TestItem;
@@ -490,7 +504,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *tree = new TestFocusScope;
QQuickItem *c1 = new TestItem(tree);
@@ -518,7 +532,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *tree = new TestFocusScope;
QQuickItem *c1 = new TestItem(tree);
@@ -544,7 +558,7 @@ void tst_qquickitem::addedToWindow()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *tree = new TestFocusScope;
@@ -584,7 +598,7 @@ void tst_qquickitem::changeParent()
// Parent to no parent
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
@@ -597,16 +611,16 @@ void tst_qquickitem::changeParent()
focusState.active(child);
FVERIFY();
- child->setParentItem(0);
+ child->setParentItem(nullptr);
focusState[child].set(true, false);
- focusState.active(0);
+ focusState.active(nullptr);
FVERIFY();
}
// Different parent, same focus scope
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *child2 = new TestItem(window.contentItem());
@@ -627,7 +641,7 @@ void tst_qquickitem::changeParent()
// Different parent, different focus scope
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *child2 = new TestFocusScope(window.contentItem());
@@ -644,12 +658,12 @@ void tst_qquickitem::changeParent()
item->setParentItem(child2);
focusState[item].set(true, false);
- focusState.active(0);
+ focusState.active(nullptr);
FVERIFY();
}
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *child2 = new TestFocusScope(window.contentItem());
@@ -661,7 +675,7 @@ void tst_qquickitem::changeParent()
item->setFocus(true);
focusState[item].set(true, false);
- focusState.active(0);
+ focusState.active(nullptr);
FVERIFY();
item->setParentItem(child);
@@ -671,7 +685,7 @@ void tst_qquickitem::changeParent()
}
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *child = new TestItem(window.contentItem());
QQuickItem *child2 = new TestFocusScope(window.contentItem());
@@ -697,7 +711,7 @@ void tst_qquickitem::changeParent()
// child is deleted, then its parent changes again to a valid parent
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem *item = new TestFocusScope(window.contentItem());
QQuickItem *child = new TestItem(item);
@@ -714,10 +728,10 @@ void tst_qquickitem::changeParent()
focusState.active(child);
FVERIFY();
- item->setParentItem(0);
+ item->setParentItem(nullptr);
focusState[child].set(true, false);
focusState[item].set(true, false);
- focusState.active(0);
+ focusState.active(nullptr);
FVERIFY();
focusState.remove(child);
@@ -736,7 +750,7 @@ void tst_qquickitem::multipleFocusClears()
QQuickView view;
view.setSource(testFileUrl("multipleFocusClears.qml"));
view.show();
- ensureFocus(&view);
+ QVERIFY(ensureFocus(&view));
QTRY_COMPARE(QGuiApplication::focusWindow(), &view);
}
@@ -745,7 +759,7 @@ void tst_qquickitem::focusSubItemInNonFocusScope()
QQuickView view;
view.setSource(testFileUrl("focusSubItemInNonFocusScope.qml"));
view.show();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickItem *dummyItem = view.rootObject()->findChild<QQuickItem *>("dummyItem");
QVERIFY(dummyItem);
@@ -767,7 +781,7 @@ void tst_qquickitem::focusSubItemInNonFocusScope()
void tst_qquickitem::parentItemWithFocus()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
{
QQuickItem parent;
@@ -866,7 +880,7 @@ void tst_qquickitem::parentItemWithFocus()
void tst_qquickitem::reparentFocusedItem()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
QQuickItem parent(window.contentItem());
@@ -937,7 +951,7 @@ void tst_qquickitem::setParentItem()
QCOMPARE(root->childItems().at(0), child1);
QCOMPARE(root->childItems().at(1), child2);
- child1->setParentItem(0);
+ child1->setParentItem(nullptr);
QVERIFY(!child1->parent());
QVERIFY(!child1->parentItem());
QCOMPARE(root->childItems().count(), 1);
@@ -1033,7 +1047,7 @@ void tst_qquickitem::enabled()
void tst_qquickitem::enabledFocus()
{
QQuickWindow window;
- ensureFocus(&window);
+ QVERIFY(ensureFocus(&window));
QQuickFocusScope root;
@@ -1224,56 +1238,56 @@ void tst_qquickitem::mouseGrab()
child2->setSize(QSizeF(200, 100));
child2->setParentItem(window.contentItem());
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(100);
QVERIFY2(window.mouseGrabberItem() == child1.data(), msgItem(window.mouseGrabberItem()).constData());
QTest::qWait(100);
QCOMPARE(child1->pressCount, 1);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(50);
- QVERIFY2(window.mouseGrabberItem() == 0, msgItem(window.mouseGrabberItem()).constData());
+ QVERIFY2(window.mouseGrabberItem() == nullptr, msgItem(window.mouseGrabberItem()).constData());
QCOMPARE(child1->releaseCount, 1);
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(50);
QVERIFY2(window.mouseGrabberItem() == child1.data(), msgItem(window.mouseGrabberItem()).constData());
QCOMPARE(child1->pressCount, 2);
child1->setEnabled(false);
- QVERIFY2(window.mouseGrabberItem() == 0, msgItem(window.mouseGrabberItem()).constData());
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QVERIFY2(window.mouseGrabberItem() == nullptr, msgItem(window.mouseGrabberItem()).constData());
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(50);
QCOMPARE(child1->releaseCount, 1);
child1->setEnabled(true);
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(50);
QVERIFY2(window.mouseGrabberItem() == child1.data(), msgItem(window.mouseGrabberItem()).constData());
QCOMPARE(child1->pressCount, 3);
child1->setVisible(false);
- QVERIFY2(window.mouseGrabberItem() == 0, msgItem(window.mouseGrabberItem()));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QVERIFY2(window.mouseGrabberItem() == nullptr, msgItem(window.mouseGrabberItem()));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QCOMPARE(child1->releaseCount, 1);
child1->setVisible(true);
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(50);
QVERIFY2(window.mouseGrabberItem() == child1.data(), msgItem(window.mouseGrabberItem()).constData());
QCOMPARE(child1->pressCount, 4);
child2->grabMouse();
QVERIFY2(window.mouseGrabberItem() == child2.data(), msgItem(window.mouseGrabberItem()).constData());
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(50);
QCOMPARE(child1->releaseCount, 1);
QCOMPARE(child2->releaseCount, 1);
child2->grabMouse();
QVERIFY2(window.mouseGrabberItem() == child2.data(), msgItem(window.mouseGrabberItem()).constData());
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(50);
QCOMPARE(child1->pressCount, 4);
QCOMPARE(child2->pressCount, 1);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50,50));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::qWait(50);
QCOMPARE(child1->releaseCount, 1);
QCOMPARE(child2->releaseCount, 2);
@@ -1294,14 +1308,14 @@ void tst_qquickitem::touchEventAcceptIgnore()
TestWindow window;
window.resize(100, 100);
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
QScopedPointer<TestItem> item(new TestItem);
item->setSize(QSizeF(100, 100));
item->setParentItem(window.contentItem());
item->acceptIncomingTouchEvents = itemSupportsTouch;
- static QTouchDevice* device = 0;
+ static QTouchDevice* device = nullptr;
if (!device) {
device =new QTouchDevice;
device->setType(QTouchDevice::TouchScreen);
@@ -1405,7 +1419,7 @@ void tst_qquickitem::polishOnCompleted()
QQuickView view;
view.setSource(testFileUrl("polishOnCompleted.qml"));
view.show();
- QTest::qWaitForWindowExposed(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
TestPolishItem *item = qobject_cast<TestPolishItem*>(view.rootObject());
QVERIFY(item);
@@ -1437,7 +1451,7 @@ void tst_qquickitem::wheelEvent()
QQuickWindow window;
window.resize(width, height);
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
TestItem *item = new TestItem;
item->setSize(QSizeF(width, height));
@@ -1469,7 +1483,7 @@ class HoverItem : public QQuickItem
{
Q_OBJECT
public:
- HoverItem(QQuickItem *parent = 0)
+ HoverItem(QQuickItem *parent = nullptr)
: QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0)
{ }
void resetCounters() {
@@ -1515,7 +1529,7 @@ void tst_qquickitem::hoverEvent_data()
// ### For some unknown reason QTest::mouseMove() isn't working correctly.
static void sendMouseMove(QObject *object, const QPoint &position)
{
- QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0);
+ QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, nullptr);
QGuiApplication::sendEvent(object, &moveEvent);
}
@@ -1731,54 +1745,54 @@ void tst_qquickitem::acceptedMouseButtons()
item.setSize(QSizeF(200,100));
item.setParentItem(window.contentItem());
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 0);
QCOMPARE(item.releaseCount, 0);
- QTest::mousePress(&window, Qt::RightButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::RightButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::RightButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::RightButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 0);
QCOMPARE(item.releaseCount, 0);
- QTest::mousePress(&window, Qt::MiddleButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::MiddleButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::MiddleButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::MiddleButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 0);
QCOMPARE(item.releaseCount, 0);
item.setAcceptedMouseButtons(Qt::LeftButton);
QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::LeftButton));
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 1);
QCOMPARE(item.releaseCount, 1);
- QTest::mousePress(&window, Qt::RightButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::RightButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::RightButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::RightButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 1);
QCOMPARE(item.releaseCount, 1);
- QTest::mousePress(&window, Qt::MiddleButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::MiddleButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::MiddleButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::MiddleButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 1);
QCOMPARE(item.releaseCount, 1);
item.setAcceptedMouseButtons(Qt::RightButton | Qt::MiddleButton);
QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::RightButton | Qt::MiddleButton));
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 1);
QCOMPARE(item.releaseCount, 1);
- QTest::mousePress(&window, Qt::RightButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::RightButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::RightButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::RightButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 2);
QCOMPARE(item.releaseCount, 2);
- QTest::mousePress(&window, Qt::MiddleButton, 0, QPoint(50, 50));
- QTest::mouseRelease(&window, Qt::MiddleButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::MiddleButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mouseRelease(&window, Qt::MiddleButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 3);
QCOMPARE(item.releaseCount, 3);
}
@@ -1786,7 +1800,7 @@ void tst_qquickitem::acceptedMouseButtons()
static void gc(QQmlEngine &engine)
{
engine.collectGarbage();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
}
@@ -1812,7 +1826,7 @@ void tst_qquickitem::visualParentOwnership()
gc(engine);
QVERIFY(!newItem.isNull());
- newItem->setParentItem(0);
+ newItem->setParentItem(nullptr);
gc(engine);
QVERIFY(newItem.isNull());
@@ -1869,7 +1883,7 @@ void tst_qquickitem::visualParentOwnershipWindow()
gc(engine);
QVERIFY(!newItem.isNull());
- newItem->setParentItem(0);
+ newItem->setParentItem(nullptr);
gc(engine);
QVERIFY(newItem.isNull());
@@ -2045,10 +2059,10 @@ void tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons()
item.setAcceptedMouseButtons(Qt::LeftButton);
QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::LeftButton));
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50, 50));
- QTest::mousePress(&window, Qt::RightButton, 0, QPoint(50, 50)); // ignored because it's not LeftButton
- QTest::mouseRelease(&window, Qt::RightButton, 0, QPoint(50, 50)); // ignored because it didn't grab the RightButton press
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
+ QTest::mousePress(&window, Qt::RightButton, Qt::NoModifier, QPoint(50, 50)); // ignored because it's not LeftButton
+ QTest::mouseRelease(&window, Qt::RightButton, Qt::NoModifier, QPoint(50, 50)); // ignored because it didn't grab the RightButton press
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
QCOMPARE(item.pressCount, 1);
QCOMPARE(item.releaseCount, 1);
@@ -2058,7 +2072,7 @@ void tst_qquickitem::shortcutOverride()
{
QQuickView view;
view.setSource(testFileUrl("shortcutOverride.qml"));
- ensureFocus(&view);
+ QVERIFY(ensureFocus(&view));
QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount").toInt(), 0);
QCOMPARE(view.rootObject()->property("shortcutActivationCount").toInt(), 0);
@@ -2087,6 +2101,51 @@ void tst_qquickitem::shortcutOverride()
QCOMPARE(view.rootObject()->property("shortcutActivationCount").toInt(), 1);
}
+#ifdef TEST_QTBUG_60123
+void tst_qquickitem::qtBug60123()
+{
+ QMainWindow main;
+ main.resize(400, 200);
+
+ QQuickView window;
+ QQuickView window2;
+ window.setSource(testFileUrl("mainWindowQtBug60123.qml"));
+ window2.setSource(testFileUrl("mainWindowQtBug60123.qml"));
+
+ // Create central widget for the main window
+ QWidget *baseWidget = new QWidget(&main);
+ baseWidget->resize(400, 200);
+ baseWidget->setMaximumHeight(200);
+ baseWidget->setMaximumWidth(400);
+ main.setCentralWidget(baseWidget);
+
+ // Create container widgets for both windows
+ QWidget *containers = QWidget::createWindowContainer(&window, baseWidget);
+ QWidget *containers2 = QWidget::createWindowContainer(&window2, baseWidget);
+ containers->setGeometry(0, 0, 100, 100);
+ containers2->setGeometry(100, 100, 100, 100);
+
+ // Show and activate the main window
+ main.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&main));
+
+ // Activate window, test press and release events
+ auto activateWindowAndTestPress = [] (QQuickView* testWindow) {
+ testWindow->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(testWindow));
+ QTest::mousePress(testWindow, Qt::LeftButton, Qt::NoModifier, QPoint(10, 10));
+ QCOMPARE(testWindow->rootObject()->property("lastEvent").toString(), QString("pressed"));
+ QTest::mouseRelease(testWindow, Qt::LeftButton, Qt::NoModifier, QPoint(10, 10));
+ QCOMPARE(testWindow->rootObject()->property("lastEvent").toString(), QString("released"));
+ };
+
+ // First press after switching focus window resulted in cancelled event
+ activateWindowAndTestPress(&window);
+ activateWindowAndTestPress(&window2);
+ activateWindowAndTestPress(&window);
+}
+#endif
+
QTEST_MAIN(tst_qquickitem)
#include "tst_qquickitem.moc"
diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop.qml
new file mode 100644
index 0000000000..889e480f3b
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.6
+
+Item {
+ visible: true
+ Item {
+ visible: false
+ Item {
+ objectName: "hiddenChild"
+ activeFocusOnTab: true
+ focus: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
index b410b445c5..596dedab90 100644
--- a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
@@ -39,6 +39,11 @@ Item {
Item { id: itemB; objectName: "itemB"; x: 100; y: 100 }
}
+ Component {
+ id: itemComponent
+ Item { x: 150; y: 150 }
+ }
+
function mapAToB(x, y) {
var pos = itemA.mapToItem(itemB, x, y)
return Qt.point(pos.x, pos.y)
@@ -69,6 +74,18 @@ Item {
return Qt.point(pos.x, pos.y)
}
+ function mapOrphanToGlobal(x, y) {
+ var obj = itemComponent.createObject(null);
+ var pos = obj.mapToGlobal(x, y)
+ return Qt.point(pos.x, pos.y)
+ }
+
+ function mapOrphanFromGlobal(x, y) {
+ var obj = itemComponent.createObject(null);
+ var pos = obj.mapFromGlobal(x, y)
+ return Qt.point(pos.x, pos.y)
+ }
+
function checkMapAToInvalid(x, y) {
try {
itemA.mapToItem(1122, x, y)
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 09e89ff85f..7107f4d995 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -64,6 +64,7 @@ private slots:
void activeFocusOnTab8();
void activeFocusOnTab9();
void activeFocusOnTab10();
+ void activeFocusOnTab_infiniteLoop();
void nextItemInFocusChain();
void nextItemInFocusChain2();
@@ -193,7 +194,7 @@ class KeyTestItem : public QQuickItem
{
Q_OBJECT
public:
- KeyTestItem(QQuickItem *parent=0) : QQuickItem(parent), mKey(0) {}
+ KeyTestItem(QQuickItem *parent=nullptr) : QQuickItem(parent), mKey(0) {}
protected:
void keyPressEvent(QKeyEvent *e) {
@@ -240,7 +241,7 @@ class HollowTestItem : public QQuickItem
Q_PROPERTY(qreal holeRadius READ holeRadius WRITE setHoleRadius)
public:
- HollowTestItem(QQuickItem *parent = 0)
+ HollowTestItem(QQuickItem *parent = nullptr)
: QQuickItem(parent),
m_isPressed(false),
m_isHovered(false),
@@ -301,7 +302,7 @@ class TabFenceItem : public QQuickItem
Q_OBJECT
public:
- TabFenceItem(QQuickItem *parent = Q_NULLPTR)
+ TabFenceItem(QQuickItem *parent = nullptr)
: QQuickItem(parent)
{
QQuickItemPrivate *d = QQuickItemPrivate::get(this);
@@ -316,7 +317,7 @@ class TabFenceItem2 : public QQuickItem
Q_OBJECT
public:
- TabFenceItem2(QQuickItem *parent = Q_NULLPTR)
+ TabFenceItem2(QQuickItem *parent = nullptr)
: QQuickItem(parent)
{
QQuickItemPrivate *d = QQuickItemPrivate::get(this);
@@ -343,7 +344,7 @@ void tst_QQuickItem::initTestCase()
void tst_QQuickItem::cleanup()
{
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
- inputMethodPrivate->testContext = 0;
+ inputMethodPrivate->testContext = nullptr;
}
void tst_QQuickItem::activeFocusOnTab()
@@ -351,7 +352,7 @@ void tst_QQuickItem::activeFocusOnTab()
if (!qt_tab_all_widgets())
QSKIP("This function doesn't support NOT iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("activeFocusOnTab.qml"));
@@ -463,7 +464,7 @@ void tst_QQuickItem::activeFocusOnTab2()
if (!qt_tab_all_widgets())
QSKIP("This function doesn't support NOT iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("activeFocusOnTab.qml"));
@@ -503,7 +504,7 @@ void tst_QQuickItem::activeFocusOnTab3()
if (!qt_tab_all_widgets())
QSKIP("This function doesn't support NOT iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("activeFocusOnTab3.qml"));
@@ -685,7 +686,7 @@ void tst_QQuickItem::activeFocusOnTab4()
if (!qt_tab_all_widgets())
QSKIP("This function doesn't support NOT iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("activeFocusOnTab4.qml"));
@@ -717,7 +718,7 @@ void tst_QQuickItem::activeFocusOnTab5()
if (!qt_tab_all_widgets())
QSKIP("This function doesn't support NOT iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("activeFocusOnTab4.qml"));
@@ -751,7 +752,7 @@ void tst_QQuickItem::activeFocusOnTab6()
if (qt_tab_all_widgets())
QSKIP("This function doesn't support iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("activeFocusOnTab6.qml"));
@@ -809,7 +810,7 @@ void tst_QQuickItem::activeFocusOnTab7()
if (qt_tab_all_widgets())
QSKIP("This function doesn't support iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(300,300));
window->setSource(testFileUrl("activeFocusOnTab7.qml"));
@@ -842,7 +843,7 @@ void tst_QQuickItem::activeFocusOnTab7()
void tst_QQuickItem::activeFocusOnTab8()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(300,300));
window->setSource(testFileUrl("activeFocusOnTab8.qml"));
@@ -894,7 +895,7 @@ void tst_QQuickItem::activeFocusOnTab9()
if (qt_tab_all_widgets())
QSKIP("This function doesn't support iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(300,300));
window->setSource(testFileUrl("activeFocusOnTab9.qml"));
@@ -945,7 +946,7 @@ void tst_QQuickItem::activeFocusOnTab10()
if (!qt_tab_all_widgets())
QSKIP("This function doesn't support NOT iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(300,300));
window->setSource(testFileUrl("activeFocusOnTab9.qml"));
@@ -1023,12 +1024,28 @@ void tst_QQuickItem::activeFocusOnTab10()
delete window;
}
+void tst_QQuickItem::activeFocusOnTab_infiniteLoop()
+{
+ // see QTBUG-68271
+ // create a window where the currently focused item is not visible
+ QScopedPointer<QQuickView>window(new QQuickView());
+ window->setSource(testFileUrl("activeFocusOnTab_infiniteLoop.qml"));
+ window->show();
+ auto *hiddenChild = findItem<QQuickItem>(window->rootObject(), "hiddenChild");
+ QVERIFY(hiddenChild);
+
+ // move the focus - this used to result in an infinite loop
+ auto *item = hiddenChild->nextItemInFocusChain();
+ // focus is moved to the root object since there is no other candidate
+ QCOMPARE(item, window->rootObject());
+}
+
void tst_QQuickItem::nextItemInFocusChain()
{
if (!qt_tab_all_widgets())
QSKIP("This function doesn't support NOT iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("activeFocusOnTab.qml"));
@@ -1104,7 +1121,7 @@ void tst_QQuickItem::nextItemInFocusChain2()
if (qt_tab_all_widgets())
QSKIP("This function doesn't support iterating all.");
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("activeFocusOnTab6.qml"));
@@ -1149,7 +1166,7 @@ void tst_QQuickItem::nextItemInFocusChain2()
void tst_QQuickItem::nextItemInFocusChain3()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("nextItemInFocusChain3.qml"));
@@ -1177,7 +1194,7 @@ void verifyTabFocusChain(QQuickView *window, const char **focusChain, bool forwa
void tst_QQuickItem::tabFence()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("tabFence.qml"));
@@ -1188,12 +1205,12 @@ void tst_QQuickItem::tabFence()
QVERIFY(window->rootObject()->hasActiveFocus());
const char *rootTabFocusChain[] = {
- "input1", "input2", "input3", "input1", Q_NULLPTR
+ "input1", "input2", "input3", "input1", nullptr
};
verifyTabFocusChain(window, rootTabFocusChain, true /* forward */);
const char *rootBacktabFocusChain[] = {
- "input3", "input2", "input1", "input3", Q_NULLPTR
+ "input3", "input2", "input1", "input3", nullptr
};
verifyTabFocusChain(window, rootBacktabFocusChain, false /* forward */);
@@ -1204,19 +1221,19 @@ void tst_QQuickItem::tabFence()
QVERIFY(item->hasActiveFocus());
const char *fence1TabFocusChain[] = {
- "input12", "input13", "input11", "input12", Q_NULLPTR
+ "input12", "input13", "input11", "input12", nullptr
};
verifyTabFocusChain(window, fence1TabFocusChain, true /* forward */);
const char *fence1BacktabFocusChain[] = {
- "input11", "input13", "input12", "input11", Q_NULLPTR
+ "input11", "input13", "input12", "input11", nullptr
};
verifyTabFocusChain(window, fence1BacktabFocusChain, false /* forward */);
}
void tst_QQuickItem::qtbug_50516()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("qtbug_50516.qml"));
@@ -1261,7 +1278,7 @@ void tst_QQuickItem::qtbug_50516_2()
QFETCH(QString, item1);
QFETCH(QString, item2);
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl(filename));
@@ -1282,7 +1299,7 @@ void tst_QQuickItem::qtbug_50516_2()
void tst_QQuickItem::keys()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
KeysTestObject *testObject = new KeysTestObject;
@@ -1471,7 +1488,7 @@ void tst_QQuickItem::standardKeys()
void tst_QQuickItem::keysProcessingOrder()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
KeysTestObject *testObject = new KeysTestObject;
@@ -1532,7 +1549,7 @@ void tst_QQuickItem::keysim()
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
inputMethodPrivate->testContext = &platformInputContext;
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
window->setSource(testFileUrl("keysim.qml"));
@@ -1650,7 +1667,7 @@ bool anchorsMirrored(QQuickItem *rootItem, const char * itemString)
void tst_QQuickItem::layoutMirroring()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("layoutmirroring.qml"));
window->show();
@@ -1801,7 +1818,7 @@ void tst_QQuickItem::layoutMirroringIllegalParent()
component.setData("import QtQuick 2.0; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile(""));
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1:21: QML QtObject: LayoutDirection attached property only works with Items and Windows");
QObject *object = component.create();
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
}
void tst_QQuickItem::keyNavigation_data()
@@ -1815,7 +1832,7 @@ void tst_QQuickItem::keyNavigation()
{
QFETCH(QString, source);
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
window->setSource(testFileUrl(source));
@@ -1892,7 +1909,7 @@ void tst_QQuickItem::keyNavigation()
void tst_QQuickItem::keyNavigation_RightToLeft()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
window->setSource(testFileUrl("keynavigationtest.qml"));
@@ -1947,7 +1964,7 @@ void tst_QQuickItem::keyNavigation_RightToLeft()
void tst_QQuickItem::keyNavigation_skipNotVisible()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
window->setSource(testFileUrl("keynavigationtest.qml"));
@@ -2022,7 +2039,7 @@ void tst_QQuickItem::keyNavigation_skipNotVisible()
void tst_QQuickItem::keyNavigation_implicitSetting()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
window->setSource(testFileUrl("keynavigationtest_implicit.qml"));
@@ -2149,7 +2166,7 @@ void tst_QQuickItem::keyNavigation_implicitSetting()
void tst_QQuickItem::keyNavigation_focusReason()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
FocusEventFilter focusEventFilter;
@@ -2210,7 +2227,7 @@ void tst_QQuickItem::keyNavigation_focusReason()
void tst_QQuickItem::keyNavigation_loop()
{
// QTBUG-47229
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(240,320));
window->setSource(testFileUrl("keynavigationtest_loop.qml"));
@@ -2325,18 +2342,18 @@ void tst_QQuickItem::mapCoordinates()
QFETCH(int, x);
QFETCH(int, y);
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(300, 300));
window->setSource(testFileUrl("mapCoordinates.qml"));
window->show();
qApp->processEvents();
QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QQuickItem *a = findItem<QQuickItem>(window->rootObject(), "itemA");
- QVERIFY(a != 0);
+ QVERIFY(a != nullptr);
QQuickItem *b = findItem<QQuickItem>(window->rootObject(), "itemB");
- QVERIFY(b != 0);
+ QVERIFY(b != nullptr);
QVariant result;
@@ -2364,6 +2381,16 @@ void tst_QQuickItem::mapCoordinates()
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromGlobal(QPointF(x, y)));
+ // for orphans we are primarily testing that we don't crash.
+ // when orphaned the final position is the original position of the item translated by x,y
+ QVERIFY(QMetaObject::invokeMethod(root, "mapOrphanToGlobal",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), QPointF(150,150) + QPointF(x, y));
+
+ QVERIFY(QMetaObject::invokeMethod(root, "mapOrphanFromGlobal",
+ Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
+ QCOMPARE(result.value<QPointF>(), -QPointF(150,150) + QPointF(x, y));
+
QString warning1 = testFileUrl("mapCoordinates.qml").toString() + ":35:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item";
QString warning2 = testFileUrl("mapCoordinates.qml").toString() + ":35:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item";
@@ -2396,18 +2423,18 @@ void tst_QQuickItem::mapCoordinatesRect()
QFETCH(int, width);
QFETCH(int, height);
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(300, 300));
window->setSource(testFileUrl("mapCoordinatesRect.qml"));
window->show();
qApp->processEvents();
QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QQuickItem *a = findItem<QQuickItem>(window->rootObject(), "itemA");
- QVERIFY(a != 0);
+ QVERIFY(a != nullptr);
QQuickItem *b = findItem<QQuickItem>(window->rootObject(), "itemB");
- QVERIFY(b != 0);
+ QVERIFY(b != nullptr);
QVariant result;
@@ -2478,7 +2505,7 @@ void tst_QQuickItem::transforms()
component.setData("import QtQuick 2.3\nItem { transform: "+qml+"}", QUrl::fromLocalFile(""));
QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
- QCOMPARE(item->itemTransform(0,0), transform);
+ QCOMPARE(item->itemTransform(nullptr,nullptr), transform);
}
void tst_QQuickItem::childrenProperty()
@@ -2486,7 +2513,7 @@ void tst_QQuickItem::childrenProperty()
QQmlComponent component(&engine, testFileUrl("childrenProperty.qml"));
QObject *o = component.create();
- QVERIFY(o != 0);
+ QVERIFY(o != nullptr);
QCOMPARE(o->property("test1").toBool(), true);
QCOMPARE(o->property("test2").toBool(), true);
@@ -2501,7 +2528,7 @@ void tst_QQuickItem::resourcesProperty()
QQmlComponent component(&engine, testFileUrl("resourcesProperty.qml"));
QObject *object = component.create();
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
QQmlProperty property(object, "resources", component.creationContext());
@@ -2533,7 +2560,7 @@ void tst_QQuickItem::resourcesProperty()
void tst_QQuickItem::propertyChanges()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(300, 300));
window->setSource(testFileUrl("propertychanges.qml"));
window->show();
@@ -2624,7 +2651,7 @@ void tst_QQuickItem::nonexistentPropertyConnection()
void tst_QQuickItem::childrenRect()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("childrenRect.qml"));
window->setBaseSize(QSize(240,320));
window->show();
@@ -2653,7 +2680,7 @@ void tst_QQuickItem::childrenRect()
// QTBUG-11383
void tst_QQuickItem::childrenRectBug()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
QString warning = testFileUrl("childrenRectBug.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
@@ -2674,7 +2701,7 @@ void tst_QQuickItem::childrenRectBug()
// QTBUG-11465
void tst_QQuickItem::childrenRectBug2()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
QString warning1 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"width\"";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
@@ -2708,7 +2735,7 @@ void tst_QQuickItem::childrenRectBug2()
// QTBUG-12722
void tst_QQuickItem::childrenRectBug3()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("childrenRectBug3.qml"));
window->show();
@@ -2719,7 +2746,7 @@ void tst_QQuickItem::childrenRectBug3()
// QTBUG-38732
void tst_QQuickItem::childrenRectBottomRightCorner()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("childrenRectBottomRightCorner.qml"));
window->show();
@@ -2811,7 +2838,7 @@ void tst_QQuickItem::changeListener()
{
QQuickWindow window;
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickItem *item = new QQuickItem;
TestListener itemListener;
@@ -2994,7 +3021,7 @@ void tst_QQuickItem::changeListener()
// QTBUG-13893
void tst_QQuickItem::transformCrash()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("transformCrash.qml"));
window->show();
@@ -3003,7 +3030,7 @@ void tst_QQuickItem::transformCrash()
void tst_QQuickItem::implicitSize()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("implicitsize.qml"));
window->show();
@@ -3076,14 +3103,14 @@ void tst_QQuickItem::qtbug_16871()
{
QQmlComponent component(&engine, testFileUrl("qtbug_16871.qml"));
QObject *o = component.create();
- QVERIFY(o != 0);
+ QVERIFY(o != nullptr);
delete o;
}
void tst_QQuickItem::visibleChildren()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("visiblechildren.qml"));
window->show();
@@ -3141,7 +3168,7 @@ void tst_QQuickItem::visibleChildren()
void tst_QQuickItem::parentLoop()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
#if QT_CONFIG(regularexpression)
QRegularExpression msgRegexp = QRegularExpression("QQuickItem::setParentItem: Parent QQuickItem\\(.*\\) is already part of the subtree of QQuickItem\\(.*\\)");
@@ -3231,7 +3258,7 @@ void tst_QQuickItem::contains()
QFETCH(bool, insideTarget);
QFETCH(QList<QPoint>, points);
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->rootContext()->setContextProperty("circleShapeTest", circleTest);
window->setBaseSize(QSize(400, 400));
window->setSource(testFileUrl("hollowTestItem.qml"));
@@ -3253,12 +3280,12 @@ void tst_QQuickItem::contains()
QCOMPARE(hollowItem->isHovered(), insideTarget);
// check mouse press
- QTest::mousePress(window, Qt::LeftButton, 0, point);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, point);
QTest::qWait(10);
QCOMPARE(hollowItem->isPressed(), insideTarget);
// check mouse release
- QTest::mouseRelease(window, Qt::LeftButton, 0, point);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, point);
QTest::qWait(10);
QCOMPARE(hollowItem->isPressed(), false);
}
@@ -3299,16 +3326,20 @@ void tst_QQuickItem::childAt()
QCOMPARE(parent.childAt(75, 75), &child2);
QCOMPARE(parent.childAt(149, 149), &child2);
QCOMPARE(parent.childAt(25, 200), &child3);
- QCOMPARE(parent.childAt(0, 150), static_cast<QQuickItem *>(0));
- QCOMPARE(parent.childAt(300, 300), static_cast<QQuickItem *>(0));
+ QCOMPARE(parent.childAt(0, 150), static_cast<QQuickItem *>(nullptr));
+ QCOMPARE(parent.childAt(300, 300), static_cast<QQuickItem *>(nullptr));
}
void tst_QQuickItem::grab()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabToImage not functional on offscreen/minimimal platforms");
+
QQuickView view;
view.setSource(testFileUrl("grabToImage.qml"));
view.show();
- QTest::qWaitForWindowExposed(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QQuickItem *root = qobject_cast<QQuickItem *>(view.rootObject());
QVERIFY(root);
diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
index 5419778cfc..1a289a2087 100644
--- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
+++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
@@ -36,6 +36,9 @@
#include "../../shared/util.h"
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+
class tst_QQuickItemLayer: public QQmlDataTest
{
Q_OBJECT
@@ -54,7 +57,7 @@ public:
}
private slots:
- void initTestCase() Q_DECL_OVERRIDE;
+ void initTestCase() override;
void layerEnabled();
void layerSmooth();
#if QT_CONFIG(opengl)
@@ -86,55 +89,52 @@ private slots:
private:
void mirroringCheck(int mirroring, int x, bool shouldMirror, const QImage &fb);
- bool m_isMesaSoftwareRasterizer;
- int m_mesaVersion;
- bool m_isOpenGLRenderer;
+ bool m_isMesaSoftwareRasterizer = false;
+ int m_mesaVersion = 0;
+ bool m_isOpenGLRenderer = true;
};
-tst_QQuickItemLayer::tst_QQuickItemLayer()
- : m_isMesaSoftwareRasterizer(false)
- , m_mesaVersion(0)
- , m_isOpenGLRenderer(true)
-{
-}
+tst_QQuickItemLayer::tst_QQuickItemLayer() { }
void tst_QQuickItemLayer::initTestCase()
{
QQmlDataTest::initTestCase();
#if QT_CONFIG(opengl)
- QWindow window;
- QOpenGLContext context;
- window.setSurfaceType(QWindow::OpenGLSurface);
- window.create();
- QVERIFY(context.create());
- QVERIFY(context.makeCurrent(&window));
- const char *vendor = (const char *)context.functions()->glGetString(GL_VENDOR);
- const char *renderer = (const char *)context.functions()->glGetString(GL_RENDERER);
- m_isMesaSoftwareRasterizer = strcmp(vendor, "Mesa Project") == 0
- && strcmp(renderer, "Software Rasterizer") == 0;
- if (m_isMesaSoftwareRasterizer) {
- // Expects format: <OpenGL version> Mesa <Mesa version>[-devel] [...]
- const char *version = (const char *)context.functions()->glGetString(GL_VERSION);
- QList<QByteArray> list = QByteArray(version).split(' ');
- if (list.size() >= 3) {
- list = list.at(2).split('-').at(0).split('.');
- int major = 0;
- int minor = 0;
- int patch = 0;
- if (list.size() >= 1)
- major = list.at(0).toInt();
- if (list.size() >= 2)
- minor = list.at(1).toInt();
- if (list.size() >= 3)
- patch = list.at(2).toInt();
- m_mesaVersion = QT_VERSION_CHECK(major, minor, patch);
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
+ QWindow window;
+ QOpenGLContext context;
+ window.setSurfaceType(QWindow::OpenGLSurface);
+ window.create();
+ QVERIFY(context.create());
+ QVERIFY(context.makeCurrent(&window));
+ const char *vendor = (const char *)context.functions()->glGetString(GL_VENDOR);
+ const char *renderer = (const char *)context.functions()->glGetString(GL_RENDERER);
+ m_isMesaSoftwareRasterizer = strcmp(vendor, "Mesa Project") == 0
+ && strcmp(renderer, "Software Rasterizer") == 0;
+ if (m_isMesaSoftwareRasterizer) {
+ // Expects format: <OpenGL version> Mesa <Mesa version>[-devel] [...]
+ const char *version = (const char *)context.functions()->glGetString(GL_VERSION);
+ QList<QByteArray> list = QByteArray(version).split(' ');
+ if (list.size() >= 3) {
+ list = list.at(2).split('-').at(0).split('.');
+ int major = 0;
+ int minor = 0;
+ int patch = 0;
+ if (list.size() >= 1)
+ major = list.at(0).toInt();
+ if (list.size() >= 2)
+ minor = list.at(1).toInt();
+ if (list.size() >= 3)
+ patch = list.at(2).toInt();
+ m_mesaVersion = QT_VERSION_CHECK(major, minor, patch);
+ }
}
+ window.create();
}
- window.create();
#endif
QQuickView view;
view.showNormal();
- QTest::qWaitForWindowExposed(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
if (view.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL)
m_isOpenGLRenderer = false;
}
@@ -147,6 +147,11 @@ void tst_QQuickItemLayer::layerSmooth()
{
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("Smooth.qml");
QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0));
QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0, 0xff));
@@ -166,6 +171,11 @@ void tst_QQuickItemLayer::layerEnabled()
{
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("Enabled.qml");
// Verify the banding
QCOMPARE(fb.pixel(0, 0), fb.pixel(0, 1));
@@ -181,6 +191,7 @@ void tst_QQuickItemLayer::layerMipmap()
{
if (m_isMesaSoftwareRasterizer)
QSKIP("Mipmapping does not work with the Mesa Software Rasterizer.");
+
QImage fb = runTest("Mipmap.qml");
QVERIFY(fb.pixel(0, 0) != 0xff000000);
QVERIFY(fb.pixel(0, 0) != 0xffffffff);
@@ -195,6 +206,11 @@ void tst_QQuickItemLayer::layerEffect()
{
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("Effect.qml");
QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0));
QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0xff, 0));
@@ -286,7 +302,7 @@ void tst_QQuickItemLayer::layerVisibility()
view.show();
- QTest::qWaitForWindowExposed(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QImage fb = view.grabWindow();
uint pixel = fb.pixel(0, 0);
@@ -451,6 +467,10 @@ void tst_QQuickItemLayer::itemEffect()
void tst_QQuickItemLayer::rectangleEffect()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("RectangleEffect.qml");
QCOMPARE(fb.pixel(0, 0), qRgb(0, 0xff, 0));
QCOMPARE(fb.pixel(199, 0), qRgb(0, 0xff, 0));
@@ -488,7 +508,7 @@ void tst_QQuickItemLayer::textureMirroring()
view.show();
- QTest::qWaitForWindowExposed(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QImage fb = view.grabWindow();
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml
index 22205c18f0..b72bc60835 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/Container.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml
index 248652e82b..364e2cc9b2 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml
index ff7ce6221b..f6c1199218 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
@@ -47,7 +57,6 @@ Container {
Text {
objectName: "qtbug51927-text"
text: qsTr("Hello World")
- anchors.centerIn: parent
renderType: Text.QtRendering
}
}
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml
index 9def782d4a..7439fe00e9 100644
--- a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml
new file mode 100644
index 0000000000..39500cc19d
--- /dev/null
+++ b/tests/auto/quick/qquicklayouts/data/rowlayout/LayerEnabled.qml
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "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 COPYRIGHT
+** OWNER OR CONTRIBUTORS 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Layouts 1.3
+
+Rectangle {
+ width: 100
+ height: 100
+ color: "black"
+
+ property alias layout: layout
+ property alias item1: r1
+
+ RowLayout {
+ id: layout
+ anchors.fill: parent
+ visible: false
+ spacing: 0
+
+ Rectangle {
+ id: r1
+ color: "red"
+
+ layer.enabled: true
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
index 4346c5283e..07af6a77ac 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
@@ -68,6 +68,66 @@ Item {
return [item.x, item.y, item.width, item.height];
}
+ Component {
+ id: itemsWithAnchorsLayout_Component
+ RowLayout {
+ spacing: 2
+ Item {
+ anchors.fill: parent
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ Item {
+ anchors.centerIn: parent
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ Item {
+ anchors.left: parent.left
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ Item {
+ anchors.right: parent.right
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ Item {
+ anchors.top: parent.top
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ Item {
+ anchors.bottom: parent.bottom
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ Item {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ Item {
+ anchors.margins: 42 // although silly, it should not cause a warning from the Layouts POV
+ implicitWidth: 10
+ implicitHeight: 10
+ }
+ }
+ }
+
+ function test_warnAboutLayoutItemsWithAnchors()
+ {
+ var fullPath = Qt.resolvedUrl("tst_rowlayout.qml")
+ for (var i = 0; i < 7; ++i) {
+ ignoreWarning(fullPath + ":" + (75 + 5*i) +":17: QML Item: Detected anchors on an item that is managed by a layout. "
+ + "This is undefined behavior; use Layout.alignment instead.")
+ }
+ var layout = itemsWithAnchorsLayout_Component.createObject(container)
+ waitForRendering(layout)
+ layout.destroy()
+ }
+
function test_fixedAndExpanding() {
var test_layoutStr =
'import QtQuick 2.2; \
@@ -263,6 +323,41 @@ Item {
col.destroy()
}
+ function test_dynamicSizeAdaptationsForInitiallyInvisibleItemsInLayout() {
+ var test_layoutStr =
+ 'import QtQuick 2.2; \
+ import QtQuick.Layouts 1.0; \
+ RowLayout { \
+ id: row; \
+ width: 10; \
+ spacing: 0; \
+ property alias r1: _r1; \
+ Rectangle { \
+ id: _r1; \
+ visible: false; \
+ height: 10; \
+ Layout.fillWidth: true; \
+ color: "#8080ff"; \
+ } \
+ property alias r2: _r2; \
+ Rectangle { \
+ id: _r2; \
+ height: 10; \
+ Layout.fillWidth: true; \
+ color: "#c0c0ff"; \
+ } \
+ } '
+
+ var lay = Qt.createQmlObject(test_layoutStr, container, '');
+ compare(lay.r1.width, 0)
+ compare(lay.r2.width, 10)
+ lay.r1.visible = true;
+ waitForRendering(lay)
+ compare(lay.r1.width, 5)
+ compare(lay.r2.width, 5)
+ lay.destroy()
+ }
+
Component {
id: layoutItem_Component
Rectangle {
@@ -475,6 +570,23 @@ Item {
{ tag: "expandPrefToExplicitMin", layoutHints: [24, -1, -1], childHints: [11, 21, 31], expected:[24, 24, 31]},
{ tag: "boundPrefToExplicitMax", layoutHints: [-1, -1, 19], childHints: [11, 21, 31], expected:[11, 19, 19]},
{ tag: "boundAllToExplicitMax", layoutHints: [-1, -1, 9], childHints: [11, 21, 31], expected:[ 9, 9, 9]},
+
+ /**
+ * Test how fractional size hint values are rounded. Some hints are ceiled towards the closest integer.
+ * Note some of these tests are not authorative, but are here to demonstrate current behavior.
+ * To summarize, it seems to be:
+ * - min: always ceiled
+ * - pref: Ceils only implicit (!) hints. Might also be ceiled if explicit
+ preferred size is less than implicit minimum size, but that's just a
+ side-effect of that preferred should never be less than minimum.
+ (tag "ceilShrinkMinToPref" below)
+ * - max: never ceiled
+ */
+ { tag: "ceilImplicitMin", layoutHints: [ -1, -1, -1], childHints: [ .1, 1.1, 9.1], expected:[ 1, 2, 9.1]},
+ { tag: "ceilExplicitMin", layoutHints: [1.1, -1, -1], childHints: [ .1, 2.1, 9.1], expected:[ 2, 3, 9.1]},
+ { tag: "ceilImplicitMin2", layoutHints: [ -1, 4.1, -1], childHints: [ .1, 1.1, 9.1], expected:[ 1, 4.1, 9.1]},
+ { tag: "ceilShrinkMinToPref", layoutHints: [ -1, 2.1, -1], childHints: [ 5, 6.1, 8.1], expected:[ 3, 3, 8.1]},
+ { tag: "ceilExpandMaxToPref", layoutHints: [ -1, 6.1, -1], childHints: [1.1, 3.1, 3.1], expected:[ 2, 6.1, 6.1]},
];
}
@@ -917,6 +1029,7 @@ Item {
fixed.implicitWidth = 100
waitForRendering(layout)
+ wait(0); // Trigger processEvents() (allow LayoutRequest to be processed)
compare(itemRect(fixed), [0,0,100,20])
compare(itemRect(filler), [100,0,100,20])
}
@@ -969,5 +1082,23 @@ Item {
// Shouldn't crash upon destroying containerUser.
}
+
+ /*
+ Tests that a layout-managed item that sets layer.enabled to true
+ still renders something. This is a simpler test case that only
+ reproduces the issue when the layout that manages it is made visible
+ after component completion, but QTBUG-63269 has a more complex example
+ where this (setting visible to true afterwards) isn't necessary.
+ */
+ function test_layerEnabled() {
+ var component = Qt.createComponent("rowlayout/LayerEnabled.qml");
+ compare(component.status, Component.Ready);
+
+ var rootRect = createTemporaryObject(component, container);
+ verify(rootRect);
+ rootRect.layout.visible = true;
+ waitForRendering(rootRect.layout)
+ compare(rootRect.item1.width, 100)
+ }
}
}
diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST
index d259c11219..e22d52294f 100644
--- a/tests/auto/quick/qquicklistview/BLACKLIST
+++ b/tests/auto/quick/qquicklistview/BLACKLIST
@@ -1,7 +1,6 @@
-[QTBUG_38209]
-*
[enforceRange_withoutHighlight]
osx
#QTBUG-53863
[populateTransitions]
opensuse-42.1
+#QTBUG-65964
diff --git a/tests/auto/quick/qquicklistview/data/addoncompleted.qml b/tests/auto/quick/qquicklistview/data/addoncompleted.qml
new file mode 100644
index 0000000000..57265cb2c0
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/addoncompleted.qml
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "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 COPYRIGHT
+** OWNER OR CONTRIBUTORS 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+
+Rectangle {
+ width: 640
+ height: 480
+ color: "green"
+
+ ListModel {
+ id: listModel
+ ListElement { name: "a" }
+ ListElement { name: "b" }
+ ListElement { name: "c" }
+ ListElement { name: "d" }
+ ListElement { name: "e" }
+ ListElement { name: "f" }
+ ListElement { name: "g" }
+ ListElement { name: "h" }
+ ListElement { name: "i" }
+ ListElement { name: "j" }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: listModel
+ objectName: "view"
+
+ delegate: Rectangle {
+ height: 15
+ width: 15
+ color: "blue"
+ objectName: name
+ Component.onCompleted: {
+ if (name.length === 1 && listModel.get(index + 1).name.length === 1) {
+ for (var i = 0; i < 10; ++i)
+ listModel.insert(index + 1, {name: name + i});
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/appendDuringScrollDown.qml b/tests/auto/quick/qquicklistview/data/appendDuringScrollDown.qml
new file mode 100644
index 0000000000..af35c29143
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/appendDuringScrollDown.qml
@@ -0,0 +1,28 @@
+import QtQuick 2.6
+
+ListView {
+ width: 320; height: 240
+ focus: true
+ delegate: Text {
+ height: 40; width: parent.width
+ text: model.text
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ highlight: Rectangle { color: "red" }
+ model: ListModel {
+ ListElement { text: "0" }
+ ListElement { text: "1" }
+ ListElement { text: "2" }
+ ListElement { text: "3" }
+ ListElement { text: "4" }
+ ListElement { text: "5" }
+ ListElement { text: "6" }
+ ListElement { text: "7" }
+ ListElement { text: "8" }
+ ListElement { text: "9" }
+ }
+
+ readonly property Item topItem: itemAt(0, contentY)
+ onTopItemChanged: model.append({ "text": "new" })
+}
diff --git a/tests/auto/quick/qquicklistview/data/attachedProperties.qml b/tests/auto/quick/qquicklistview/data/attachedProperties.qml
index ffba4196f6..09714b2c6e 100644
--- a/tests/auto/quick/qquicklistview/data/attachedProperties.qml
+++ b/tests/auto/quick/qquicklistview/data/attachedProperties.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklistview/data/flickBothDirections.qml b/tests/auto/quick/qquicklistview/data/flickBothDirections.qml
index 5d80ce4110..b491981edb 100644
--- a/tests/auto/quick/qquicklistview/data/flickBothDirections.qml
+++ b/tests/auto/quick/qquicklistview/data/flickBothDirections.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
@@ -53,6 +63,7 @@ Rectangle {
contentWidth: initialContentWidth
contentHeight: initialContentHeight
flickableDirection: initialFlickableDirection
+ pixelAligned: true
delegate: Rectangle {
width: list.orientation == ListView.Vertical ? 120 : 10
height: list.orientation == ListView.Vertical ? 20 : 110
diff --git a/tests/auto/quick/qquicklistview/data/itemlist-flicker.qml b/tests/auto/quick/qquicklistview/data/itemlist-flicker.qml
index c0cc807bc0..89daadaaa5 100644
--- a/tests/auto/quick/qquicklistview/data/itemlist-flicker.qml
+++ b/tests/auto/quick/qquicklistview/data/itemlist-flicker.qml
@@ -1,33 +1,34 @@
// This example demonstrates placing items in a view using
-// a VisualItemModel
+// an ObjectModel
import QtQuick 2.0
+import QtQml.Models 2.12
Rectangle {
color: "lightgray"
width: 240
height: 320
- VisualItemModel {
+ ObjectModel {
id: itemModel
objectName: "itemModel"
Rectangle {
objectName: "item1"
height: view.height / 3
width: view.width; color: "#FFFEF0"
- Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text1"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item2"
height: view.height / 3
width: view.width; color: "#F0FFF7"
- Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text2"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item3"
height: view.height / 3
width: view.width; color: "#F4F0FF"
- Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text3"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
}
diff --git a/tests/auto/quick/qquicklistview/data/itemlist.qml b/tests/auto/quick/qquicklistview/data/itemlist.qml
index 5c7ecdd5e8..00910ae60c 100644
--- a/tests/auto/quick/qquicklistview/data/itemlist.qml
+++ b/tests/auto/quick/qquicklistview/data/itemlist.qml
@@ -1,33 +1,34 @@
// This example demonstrates placing items in a view using
-// a VisualItemModel
+// an ObjectModel
import QtQuick 2.0
+import QtQml.Models 2.12
Rectangle {
color: "lightgray"
width: 240
height: 320
- VisualItemModel {
+ ObjectModel {
id: itemModel
objectName: "itemModel"
Rectangle {
objectName: "item1"
height: ListView.view ? ListView.view.height : 0
width: view.width; color: "#FFFEF0"
- Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text1"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item2"
height: ListView.view ? ListView.view.height : 0
width: view.width; color: "#F0FFF7"
- Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text2"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item3"
height: ListView.view ? ListView.view.height : 0
width: view.width; color: "#F4F0FF"
- Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text3"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
}
diff --git a/tests/auto/quick/qquicklistview/data/listview-itematindex.qml b/tests/auto/quick/qquicklistview/data/listview-itematindex.qml
new file mode 100644
index 0000000000..fba8b11933
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/listview-itematindex.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.0
+
+ListView {
+ width: 400
+ height: 400
+ focus: true
+ model: 3
+
+ delegate: Text {
+ width: parent.width
+ height: 10
+ property int idx: index
+ text: index
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/listview-sections-package.qml b/tests/auto/quick/qquicklistview/data/listview-sections-package.qml
index 8bad73b5f6..4297ab1c69 100644
--- a/tests/auto/quick/qquicklistview/data/listview-sections-package.qml
+++ b/tests/auto/quick/qquicklistview/data/listview-sections-package.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Rectangle {
width: 240
@@ -54,7 +55,7 @@ Rectangle {
}
}
},
- VisualDataModel {
+ DelegateModel {
id: visualModel
model: testModel
delegate: myDelegate
diff --git a/tests/auto/quick/qquicklistview/data/listviewtest-package.qml b/tests/auto/quick/qquicklistview/data/listviewtest-package.qml
index 452fe29b49..c26bbece03 100644
--- a/tests/auto/quick/qquicklistview/data/listviewtest-package.qml
+++ b/tests/auto/quick/qquicklistview/data/listviewtest-package.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Rectangle {
id: root
@@ -120,7 +121,7 @@ Rectangle {
id: headerFooter
Rectangle { height: 30; width: 240; color: "blue" }
},
- VisualDataModel {
+ DelegateModel {
id: visualModel
model: testModel
diff --git a/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml b/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml
index 086f31fd70..e0acaf49e4 100644
--- a/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml
+++ b/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklistview/data/programmaticFlickAtBounds3.qml b/tests/auto/quick/qquicklistview/data/programmaticFlickAtBounds3.qml
new file mode 100644
index 0000000000..bd913b2ce1
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/programmaticFlickAtBounds3.qml
@@ -0,0 +1,19 @@
+import QtQuick 2.9
+
+ListView {
+ id: view
+ width: 200; height: 400
+
+ property real minOvershoot
+ onVerticalOvershootChanged: if (verticalOvershoot < minOvershoot) minOvershoot = verticalOvershoot
+
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ preferredHighlightBegin: 0
+ preferredHighlightEnd: 0
+
+ model: 10
+ delegate: Rectangle {
+ width: 200; height: 50
+ color: index % 2 ? "red" : "green"
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/qtbug34576.qml b/tests/auto/quick/qquicklistview/data/qtbug34576.qml
new file mode 100644
index 0000000000..f407d8ebe3
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug34576.qml
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+import QtQuick 2.7
+
+Rectangle {
+ id: root
+ width: 320
+ height: 240
+ color: "black"
+
+ property int current: list.currentIndex
+ property int horizontalVelocityZeroCount: 0
+
+ ListView {
+ id: list
+ objectName: "list"
+ anchors.fill: parent
+
+ focus: true
+
+ orientation: ListView.Horizontal
+
+ snapMode: ListView.SnapToItem
+ flickableDirection: Flickable.HorizontalFlick
+
+ model: 10
+ delegate: Item {
+ width: root.width / 3
+ height: root.height
+ Rectangle {
+ anchors.centerIn: parent
+ width: 50
+ height: 50
+ color: list.currentIndex === index ? "red" : "white"
+ }
+ }
+
+ onHorizontalVelocityChanged: {
+ if (list.horizontalVelocity === 0.0)
+ root.horizontalVelocityZeroCount++
+ }
+
+ }
+
+ Rectangle {
+ color: "red"
+ width: 50
+ height: 50
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ list.currentIndex--;
+ }
+ }
+ }
+
+ Rectangle {
+ color: "red"
+ width: 50
+ height: 50
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ list.currentIndex++;
+ }
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml b/tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml
new file mode 100644
index 0000000000..0dc9e6fdb5
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug61537_modelChangesAsync.qml
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "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 COPYRIGHT
+** OWNER OR CONTRIBUTORS 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.0
+
+Item {
+ visible: true
+ width: 640
+ height: 480
+
+ property ListView listView
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ asynchronous: true
+ sourceComponent: comp
+
+ onStatusChanged: {
+ if (status == Loader.Ready) {
+ // Assign the listview to the root prop late, so
+ // that the c++ part doesn't start before everything is ready.
+ listView = item.listView
+ }
+ }
+ }
+
+ Component {
+ id: comp
+ Item {
+ property alias listView: listView
+
+ ListView {
+ id: listView
+
+ model: ListModel {
+ id: listModel
+ ListElement { title: "one" }
+ ListElement { title: "two" }
+ }
+
+ anchors.fill: parent
+ orientation: ListView.Horizontal
+
+ delegate: Item {
+ id: delegateRoot
+ objectName: "delegate"
+
+ width: 200
+ height: 200
+
+ Component.onCompleted: {
+ if (index === listModel.count - 1) {
+ // Add a new item while the outer Loader is still incubating async. If the new model item
+ // incubates using e.g QQmlIncubator::AsynchronousIfNested, it will also be loaded async, which
+ // is not currently supported (the item will not be added to the listview, or end up the wrong
+ // position, depending on its index and the current state of the refill/layout logic in
+ // QQuickListView).
+ // We add the new item here at the last delegates Component.onCompleted to hit the point in time
+ // when the listview is not expecting any more async items. In that case, the item will only be
+ // added to the list of visible items if incubated synchronously, which gives us something we
+ // can test for in the auto-test.
+ listModel.insert(0, {title: "zero"});
+ }
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ border.width: 1
+ Text {
+ anchors.centerIn: parent
+ text: index
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/qtbug63974.qml b/tests/auto/quick/qquicklistview/data/qtbug63974.qml
new file mode 100644
index 0000000000..1e0afa54f8
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug63974.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.6
+
+ListView {
+ id: table
+ height: 200
+ width: 100
+
+ headerPositioning: ListView.OverlayHeader
+ header: Rectangle {
+ width: table.width
+ height: 20
+ color: "red"
+ z: 100
+ }
+
+ footerPositioning: ListView.OverlayFooter
+ footer: Rectangle {
+ width: table.width
+ height: 20
+ color: "blue"
+ z: 200
+ }
+
+ model: 30
+ delegate: Rectangle {
+ height: 20
+ width: table.width
+ color: "lightgray"
+ Text {
+ text: "Item " + index
+ anchors.centerIn: parent
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/releaseItems.qml b/tests/auto/quick/qquicklistview/data/releaseItems.qml
new file mode 100644
index 0000000000..de774e5e08
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/releaseItems.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+
+ListView {
+ width: 400
+ height: 400
+ model: 100
+ delegate: Rectangle {
+ height: 40; width: 400
+ color: index % 2 ? "lightsteelblue" : "lightgray"
+ }
+ contentHeight: contentItem.children.length * 40
+}
diff --git a/tests/auto/quick/qquicklistview/data/repositionResizedDelegate.qml b/tests/auto/quick/qquicklistview/data/repositionResizedDelegate.qml
index d79ca100f4..fa16a8529e 100644
--- a/tests/auto/quick/qquicklistview/data/repositionResizedDelegate.qml
+++ b/tests/auto/quick/qquicklistview/data/repositionResizedDelegate.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
ListView {
id: root
@@ -9,7 +10,7 @@ ListView {
layoutDirection: (testRightToLeft == true) ? Qt.RightToLeft : Qt.LeftToRight
verticalLayoutDirection: (testBottomToTop == true) ? ListView.BottomToTop : ListView.TopToBottom
- model: VisualItemModel {
+ model: ObjectModel {
Rectangle {
objectName: "red"
width: 200; height: 200; color: "red"
diff --git a/tests/auto/quick/qquicklistview/data/rightToLeft.qml b/tests/auto/quick/qquicklistview/data/rightToLeft.qml
index 6d77de26f4..dec7e0abc1 100644
--- a/tests/auto/quick/qquicklistview/data/rightToLeft.qml
+++ b/tests/auto/quick/qquicklistview/data/rightToLeft.qml
@@ -2,29 +2,30 @@
// changes in right-to-left layout direction
import QtQuick 2.0
+import QtQml.Models 2.12
Rectangle {
color: "lightgray"
width: 640
height: 320
- VisualItemModel {
+ ObjectModel {
id: itemModel
objectName: "itemModel"
Rectangle {
objectName: "item1"
height: view.height; width: 100; color: "#FFFEF0"
- Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text1"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item2"
height: view.height; width: 200; color: "#F0FFF7"
- Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text2"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item3"
height: view.height; width: 240; color: "#F4F0FF"
- Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text3"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
}
diff --git a/tests/auto/quick/qquicklistview/data/roundingErrors.qml b/tests/auto/quick/qquicklistview/data/roundingErrors.qml
index bf87415551..4545fcd617 100644
--- a/tests/auto/quick/qquicklistview/data/roundingErrors.qml
+++ b/tests/auto/quick/qquicklistview/data/roundingErrors.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklistview/data/sectionSnapping.qml b/tests/auto/quick/qquicklistview/data/sectionSnapping.qml
new file mode 100644
index 0000000000..2583cc0377
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/sectionSnapping.qml
@@ -0,0 +1,49 @@
+import QtQuick 2.0
+
+ListView {
+ width: 400
+ height: 400
+ preferredHighlightBegin: 100
+ preferredHighlightEnd: 100
+ highlightRangeMode: ListView.StrictlyEnforceRange
+
+ model: ListModel {
+ ListElement { section: "1" }
+ ListElement { section: "1" }
+ ListElement { section: "1" }
+ ListElement { section: "2" }
+ ListElement { section: "2" }
+ ListElement { section: "2" }
+ }
+
+ delegate: Rectangle {
+ width: parent.width
+ height: 50
+ color: index % 2 ? "lightsteelblue" : "steelblue"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: model.index
+ }
+ }
+
+ section.property: "section"
+ section.delegate: Rectangle {
+ width: parent.width
+ height: 50
+ color: "green"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: "section"
+ }
+ }
+
+ highlight: Rectangle {
+ y: 100
+ z: 100
+ width: parent.width
+ height: 50
+ color: "#80FF0000"
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/setpositiononlayout.qml b/tests/auto/quick/qquicklistview/data/setpositiononlayout.qml
new file mode 100644
index 0000000000..6e12eeafca
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/setpositiononlayout.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "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 COPYRIGHT
+** OWNER OR CONTRIBUTORS 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 200
+ height: 720
+
+ ListView {
+ anchors.fill: parent
+ focus: true
+ highlightMoveDuration: 200
+ model: 50
+ spacing: 10
+ delegate: FocusScope {
+ implicitHeight: col.height
+ Column {
+ id: col
+ Text {
+ text: "YYYY"
+ }
+ ListView {
+ id: list
+ model: 1
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 250
+ orientation: ListView.Horizontal
+ delegate: Rectangle {
+ id: self
+ height: 250
+ width: 150
+ color: "blue"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/sizeTransitions.qml b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
index eae96c468f..44e4dada60 100644
--- a/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
+++ b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklistview/data/snapOneItemWrongDirection.qml b/tests/auto/quick/qquicklistview/data/snapOneItemWrongDirection.qml
new file mode 100644
index 0000000000..f5b7b35d0c
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/snapOneItemWrongDirection.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.0
+
+ListView {
+ width: 400
+ height: 400
+ focus: true
+
+ model: 10
+ delegate: Rectangle {
+ width: parent.width
+ height: 50
+ color: index % 2 ? "blue" : "green"
+ }
+
+ snapMode: ListView.SnapOneItem
+ Keys.onUpPressed: flick(0,500)
+ Keys.onDownPressed: flick(0,-500)
+}
diff --git a/tests/auto/quick/qquicklistview/data/snapToItemWithSpacing.qml b/tests/auto/quick/qquicklistview/data/snapToItemWithSpacing.qml
new file mode 100644
index 0000000000..50b5abb206
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/snapToItemWithSpacing.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.0
+
+ListView {
+ width: 100
+ height: 300
+ snapMode: ListView.SnapToItem
+ spacing: 100
+ model: 10
+ delegate: Rectangle {
+ height: 100
+ width: 100
+ color: "blue"
+ Text {
+ anchors.centerIn: parent
+ text: index
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml
index f57927dbe7..57e7578ba5 100644
--- a/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml
index af5a6174f9..fd815ea79e 100644
--- a/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml
index cfd0f3dd44..94fb294474 100644
--- a/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquicklistview/data/strictlyenforcerange-resize.qml b/tests/auto/quick/qquicklistview/data/strictlyenforcerange-resize.qml
new file mode 100644
index 0000000000..338af38475
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/strictlyenforcerange-resize.qml
@@ -0,0 +1,31 @@
+import QtQuick 2.0
+
+ListView {
+ width: 400
+ height: 400
+ focus: true
+
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ highlightMoveVelocity: 200
+ preferredHighlightBegin: 150
+ preferredHighlightEnd: 150
+
+ property bool completed
+ Component.onCompleted: completed = true
+
+ model: 10
+ delegate: Item {
+ width: parent.width
+ height: ListView.isCurrentItem ? 100 : 50
+
+ Text {
+ anchors.centerIn: parent
+ text: index
+ }
+
+ Behavior on height {
+ enabled: completed
+ SmoothedAnimation { velocity: 200 }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/unrequestedItems.qml b/tests/auto/quick/qquicklistview/data/unrequestedItems.qml
index e3719a8be0..e6cb856c1e 100644
--- a/tests/auto/quick/qquicklistview/data/unrequestedItems.qml
+++ b/tests/auto/quick/qquicklistview/data/unrequestedItems.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Item {
width: 240
@@ -34,7 +35,7 @@ Item {
}
- VisualDataModel {
+ DelegateModel {
id: visualModel
delegate: myDelegate
diff --git a/tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml b/tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml
new file mode 100644
index 0000000000..45164222f2
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/usechooserwithoutdefault.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import Qt.labs.qmlmodels 1.0
+
+Item {
+ width: 640
+ height: 450
+
+ ListView {
+ width: 600
+ height: 400
+ model: 2
+ delegate: DelegateChooser {
+ DelegateChoice {
+ index: 0
+ delegate: Rectangle {
+ width: 100
+ height: 100
+ color:"green"
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/qquicklistview.pro b/tests/auto/quick/qquicklistview/qquicklistview.pro
index a95b6fdf33..fd96c269a2 100644
--- a/tests/auto/quick/qquicklistview/qquicklistview.pro
+++ b/tests/auto/quick/qquicklistview/qquicklistview.pro
@@ -16,6 +16,7 @@ include (../../shared/util.pri)
include (../shared/util.pri)
TESTDATA = data/*
+DISTFILES += data/*
-QT += core-private gui-private qml-private quick-private testlib
+QT += core-private gui-private qml-private quick-private testlib qmltest
diff --git a/tests/auto/quick/qquicklistview/randomsortmodel.cpp b/tests/auto/quick/qquicklistview/randomsortmodel.cpp
index 7affb182c0..7375fe0dbe 100644
--- a/tests/auto/quick/qquicklistview/randomsortmodel.cpp
+++ b/tests/auto/quick/qquicklistview/randomsortmodel.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include "randomsortmodel.h"
+#include <QRandomGenerator>
RandomSortModel::RandomSortModel(QObject* parent):
QAbstractListModel(parent)
@@ -73,14 +74,14 @@ QVariant RandomSortModel::data(const QModelIndex& index, int role) const
void RandomSortModel::randomize()
{
- const int row = qrand() % mData.count();
+ const int row = QRandomGenerator::global()->bounded(mData.count());
int random;
bool exists = false;
// Make sure we won't end up with two items with the same weight, as that
// would make unit-testing much harder
do {
exists = false;
- random = qrand() % (mData.count() * 10);
+ random = QRandomGenerator::global()->bounded(mData.count() * 10);
QList<QPair<QString, int> >::ConstIterator iter, end;
for (iter = mData.constBegin(), end = mData.constEnd(); iter != end; ++iter) {
if ((*iter).second == random) {
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index ff06c1e1a4..d96590bdae 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -31,6 +31,7 @@
#include <QtCore/QSortFilterProxyModel>
#include <QtGui/QStandardItemModel>
#include <QtQuick/qquickview.h>
+#include <QtQuickTest/QtQuickTest>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
@@ -118,6 +119,7 @@ private slots:
void noCurrentIndex();
void keyNavigation();
void keyNavigation_data();
+ void checkCountForMultiColumnModels();
void enforceRange();
void enforceRange_withoutHighlight();
void spacing();
@@ -131,6 +133,8 @@ private slots:
void sectionPropertyChange();
void sectionDelegateChange();
void sectionsItemInsertion();
+ void sectionsSnap_data();
+ void sectionsSnap();
void cacheBuffer();
void positionViewAtBeginningEnd();
void positionViewAtIndex();
@@ -162,6 +166,7 @@ private slots:
void QTBUG_16037();
void indexAt_itemAt_data();
void indexAt_itemAt();
+ void itemAtIndex();
void incrementalModel();
void onAdd();
void onAdd_data();
@@ -176,12 +181,15 @@ private slots:
void creationContext();
void snapToItem_data();
void snapToItem();
+ void snapToItemWithSpacing_QTBUG_59852();
void snapOneItemResize_QTBUG_43555();
void snapOneItem_data();
void snapOneItem();
void snapOneItemCurrentIndexRemoveAnimation();
+ void snapOneItemWrongDirection();
void QTBUG_9791();
+ void QTBUG_33568();
void QTBUG_11105();
void QTBUG_21742();
@@ -235,6 +243,7 @@ private slots:
void QTBUG_38209();
void programmaticFlickAtBounds();
void programmaticFlickAtBounds2();
+ void programmaticFlickAtBounds3();
void layoutChange();
@@ -252,8 +261,20 @@ private slots:
void QTBUG_50105();
void keyNavigationEnabled();
+ void QTBUG_61269_appendDuringScrollDown();
+ void QTBUG_61269_appendDuringScrollDown_data();
void QTBUG_50097_stickyHeader_positionViewAtIndex();
+ void QTBUG_63974_stickyHeader_positionViewAtIndex_Contain();
void itemFiltered();
+ void releaseItems();
+
+ void QTBUG_34576_velocityZero();
+ void QTBUG_61537_modelChangesAsync();
+
+ void useDelegateChooserWithoutDefault();
+
+ void addOnCompleted();
+ void setPositionOnLayout();
private:
template <class T> void items(const QUrl &source);
@@ -283,7 +304,7 @@ private:
if (m_view) {
if (QString(QTest::currentTestFunction()) != testForView) {
delete m_view;
- m_view = 0;
+ m_view = nullptr;
} else {
m_view->setSource(QUrl());
return m_view;
@@ -321,7 +342,7 @@ class TestObject : public QObject
Q_PROPERTY(int cacheBuffer READ cacheBuffer NOTIFY changedCacheBuffer)
public:
- TestObject(QObject *parent = 0)
+ TestObject(QObject *parent = nullptr)
: QObject(parent), mError(true), mAnimate(false), mInvalidHighlight(false)
, mCacheBuffer(0) {}
@@ -350,7 +371,7 @@ public:
int mCacheBuffer;
};
-tst_QQuickListView::tst_QQuickListView() : m_view(0)
+tst_QQuickListView::tst_QQuickListView() : m_view(nullptr)
{
}
@@ -360,7 +381,7 @@ void tst_QQuickListView::init()
if (m_view && QString(QTest::currentTestFunction()) != testForView) {
testForView = QString();
delete m_view;
- m_view = 0;
+ m_view = nullptr;
}
#endif
qmlRegisterType<QAbstractItemModel>();
@@ -373,7 +394,7 @@ void tst_QQuickListView::cleanupTestCase()
#ifdef SHARE_VIEWS
testForView = QString();
delete m_view;
- m_view = 0;
+ m_view = nullptr;
#endif
}
@@ -397,16 +418,16 @@ void tst_QQuickListView::items(const QUrl &source)
qApp->processEvents();
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->forceLayout();
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
QTRY_VERIFY(!testObject->error());
- QTRY_VERIFY(listview->highlightItem() != 0);
+ QTRY_VERIFY(listview->highlightItem() != nullptr);
QTRY_COMPARE(listview->count(), model.count());
QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
listview->forceLayout();
@@ -417,10 +438,10 @@ void tst_QQuickListView::items(const QUrl &source)
for (int i = 0; i < model.count(); ++i) {
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -442,17 +463,16 @@ void tst_QQuickListView::items(const QUrl &source)
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->currentItem());
- QTRY_VERIFY(listview->highlightItem() != 0);
+ QTRY_VERIFY(listview->highlightItem() != nullptr);
// set an empty model and confirm that items are destroyed
T model2;
ctxt->setContextProperty("testModel", &model2);
- // Force a layout, necessary if ListView is completed before VisualDataModel.
+ // Force a layout, necessary if ListView is completed before DelegateModel.
listview->forceLayout();
- int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- QTRY_COMPARE(itemCount, 0);
+ QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").isEmpty());
QTRY_COMPARE(listview->highlightResizeVelocity(), 1000.0);
QTRY_COMPARE(listview->highlightMoveVelocity(), 100000.0);
@@ -481,21 +501,21 @@ void tst_QQuickListView::changed(const QUrl &source)
qApp->processEvents();
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->forceLayout();
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
- // Force a layout, necessary if ListView is completed before VisualDataModel.
+ // Force a layout, necessary if ListView is completed before DelegateModel.
listview->forceLayout();
model.modifyItem(1, "Will", "9876");
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(1));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(1));
delete testObject;
@@ -523,10 +543,10 @@ void tst_QQuickListView::inserted(const QUrl &source)
qApp->processEvents();
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
model.insertItem(1, "Will", "9876");
@@ -534,10 +554,10 @@ void tst_QQuickListView::inserted(const QUrl &source)
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(1));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(1));
// Confirm items positioned correctly
@@ -552,10 +572,10 @@ void tst_QQuickListView::inserted(const QUrl &source)
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(0));
number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(0));
QTRY_COMPARE(listview->currentIndex(), 1);
@@ -622,13 +642,13 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
if (verticalLayoutDirection == QQuickItemView::BottomToTop) {
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
contentY = -listview->height() - contentY;
}
listview->setContentY(contentY);
@@ -641,7 +661,7 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
model.insertItems(insertIndex, newData);
//Wait for polish (updates list to the model changes)
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->property("count").toInt(), model.count());
@@ -695,10 +715,10 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
}
QTRY_COMPARE(item->y(), pos);
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
+ QVERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -817,12 +837,12 @@ void tst_QQuickListView::insertBeforeVisible()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
listview->setCacheBuffer(cacheBuffer);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// trigger a refill (not just setting contentY) so that the visibleItems grid is updated
int firstVisibleIndex = 20; // move to an index where the top item is not visible
@@ -830,7 +850,7 @@ void tst_QQuickListView::insertBeforeVisible()
listview->setCurrentIndex(firstVisibleIndex);
qApp->processEvents();
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->currentIndex(), firstVisibleIndex);
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
QVERIFY(item);
@@ -850,7 +870,7 @@ void tst_QQuickListView::insertBeforeVisible()
// now, moving to the top of the view should position the inserted items correctly
int itemsOffsetAfterMove = (removeCount - insertCount) * 20;
listview->setCurrentIndex(0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->currentIndex(), 0);
QTRY_COMPARE(listview->contentY(), 0.0 + itemsOffsetAfterMove);
@@ -861,7 +881,7 @@ void tst_QQuickListView::insertBeforeVisible()
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -930,19 +950,19 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
model.removeItem(1);
QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(1));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(1));
// Confirm items positioned correctly
@@ -959,10 +979,10 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(0));
number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(0));
// Confirm items positioned correctly
@@ -1012,7 +1032,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
listview->setContentY(20); // That's the top now
// let transitions settle.
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -1026,15 +1046,15 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
// remove current item beyond visible items.
listview->setCurrentIndex(20);
listview->setContentY(40);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
model.removeItem(20);
QTRY_COMPARE(listview->currentIndex(), 20);
- QTRY_VERIFY(listview->currentItem() != 0);
+ QTRY_VERIFY(listview->currentItem() != nullptr);
// remove item before current, but visible
listview->setCurrentIndex(8);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
oldCurrent = listview->currentItem();
model.removeItem(6);
@@ -1042,7 +1062,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
QTRY_COMPARE(listview->currentItem(), oldCurrent);
listview->setContentY(80);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// remove all visible items
model.removeItems(1, 18);
@@ -1114,20 +1134,20 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
if (verticalLayoutDirection == QQuickItemView::BottomToTop) {
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
contentY = -listview->height() - contentY;
}
listview->setContentY(contentY);
model.removeItems(removeIndex, removeCount);
//Wait for polish (updates list to the model changes)
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->property("count").toInt(), model.count());
@@ -1162,10 +1182,10 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic
pos = -item0->height() - pos;
QTRY_COMPARE(item->y(), pos);
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
+ QVERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -1296,12 +1316,12 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
model.clear();
@@ -1320,7 +1340,7 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou
model.addItem("New", "1");
listview->forceLayout();
QTRY_COMPARE(listview->count(), 1);
- QVERIFY(listview->currentItem() != 0);
+ QVERIFY(listview->currentItem() != nullptr);
QCOMPARE(listview->currentIndex(), 0);
delete testObject;
@@ -1354,25 +1374,25 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
// always need to wait for view to be painted before the first move()
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
bool waitForPolish = (contentY != 0);
if (verticalLayoutDirection == QQuickItemView::BottomToTop) {
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
contentY = -listview->height() - contentY;
}
listview->setContentY(contentY);
if (waitForPolish)
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
model.moveItems(from, to, count);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
int firstVisibleIndex = -1;
@@ -1394,10 +1414,10 @@ void tst_QQuickListView::moved(const QUrl &source, QQuickItemView::VerticalLayou
pos = -item->height() - pos;
QTRY_COMPARE(item->y(), pos);
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
+ QVERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
// current index should have been updated
@@ -1584,8 +1604,8 @@ void tst_QQuickListView::multipleChanges(bool condensed)
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(listview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
for (int i=0; i<changes.count(); i++) {
switch (changes[i].type) {
@@ -1613,10 +1633,10 @@ void tst_QQuickListView::multipleChanges(bool condensed)
continue;
}
if (!condensed) {
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
}
}
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QCOMPARE(listview->count(), newCount);
QCOMPARE(listview->count(), model.count());
@@ -1625,16 +1645,16 @@ void tst_QQuickListView::multipleChanges(bool condensed)
QQuickText *name;
QQuickText *number;
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i=0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
number = findItem<QQuickText>(contentItem, "textNumber", i);
- QVERIFY(number != 0);
+ QVERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(i));
}
@@ -1832,8 +1852,8 @@ void tst_QQuickListView::swapWithFirstItem()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(listview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// ensure content position is stable
listview->setContentY(0);
@@ -1843,6 +1863,38 @@ void tst_QQuickListView::swapWithFirstItem()
delete testObject;
}
+void tst_QQuickListView::checkCountForMultiColumnModels()
+{
+ // Check that a list view will only load items for the first
+ // column, even if the model reports that it got several columns.
+ // We test this since QQmlDelegateModel has been changed to
+ // also understand multi-column models, but this should not affect ListView.
+ QScopedPointer<QQuickView> window(createView());
+
+ const int rowCount = 10;
+ const int columnCount = 10;
+
+ QaimModel model;
+ model.columns = columnCount;
+ for (int i = 0; i < rowCount; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ QScopedPointer<TestObject> testObject(new TestObject);
+ ctxt->setContextProperty("testObject", testObject.data());
+
+ window->setSource(testFileUrl("listviewtest.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview != nullptr);
+
+ QCOMPARE(listview->count(), rowCount);
+}
+
void tst_QQuickListView::enforceRange()
{
QScopedPointer<QQuickView> window(createView());
@@ -1859,15 +1911,15 @@ void tst_QQuickListView::enforceRange()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QTRY_COMPARE(listview->preferredHighlightBegin(), 100.0);
QTRY_COMPARE(listview->preferredHighlightEnd(), 100.0);
QTRY_COMPARE(listview->highlightRangeMode(), QQuickListView::StrictlyEnforceRange);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
// view should be positioned at the top of the range.
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
@@ -1875,10 +1927,10 @@ void tst_QQuickListView::enforceRange()
QTRY_COMPARE(listview->contentY(), -100.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
- QTRY_VERIFY(name != 0);
+ QTRY_VERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(0));
QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
- QTRY_VERIFY(number != 0);
+ QTRY_VERIFY(number != nullptr);
QTRY_COMPARE(number->text(), model.number(0));
// Check currentIndex is updated when contentItem moves
@@ -1918,8 +1970,8 @@ void tst_QQuickListView::enforceRange_withoutHighlight()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(listview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
qreal expectedPos = -100.0;
@@ -1959,11 +2011,11 @@ void tst_QQuickListView::spacing()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -2017,12 +2069,12 @@ void tst_QQuickListView::sections(const QUrl &source)
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -2092,9 +2144,9 @@ void tst_QQuickListView::sections(const QUrl &source)
// check that headers change when item changes
listview->setContentY(0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
model.modifyItem(0, "changed", "2");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
item = findItem<QQuickItem>(contentItem, "wrapper", 1);
QTRY_VERIFY(item);
@@ -2117,12 +2169,12 @@ void tst_QQuickListView::sectionsDelegate()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -2146,7 +2198,7 @@ void tst_QQuickListView::sectionsDelegate()
model.modifyItem(2, "Three", "aaa");
model.modifyItem(3, "Four", "aaa");
model.modifyItem(4, "Five", "aaa");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
for (int i = 0; i < 3; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem,
@@ -2182,7 +2234,7 @@ void tst_QQuickListView::sectionsDelegate()
model.modifyItem(9, "Two", "aaa");
model.modifyItem(10, "Two", "aaa");
model.modifyItem(11, "Two", "aaa");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(findItems<QQuickItem>(contentItem, "sect_aaa").count(), 1);
window->rootObject()->setProperty("sectionProperty", "name");
// ensure view has settled.
@@ -2226,30 +2278,30 @@ void tst_QQuickListView::sectionsDragOutsideBounds()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setCacheBuffer(cacheBuffer);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// QTBUG-17769
// Drag view up beyond bounds
- QTest::mousePress(window, Qt::LeftButton, 0, QPoint(20,20));
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(20,20));
QTest::mouseMove(window, QPoint(20,0));
QTest::mouseMove(window, QPoint(20,-50));
QTest::mouseMove(window, QPoint(20,-distance));
- QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(20,-distance));
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(20,-distance));
// view should settle back at 0
QTRY_COMPARE(listview->contentY(), 0.0);
- QTest::mousePress(window, Qt::LeftButton, 0, QPoint(20,0));
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(20,0));
QTest::mouseMove(window, QPoint(20,20));
QTest::mouseMove(window, QPoint(20,70));
QTest::mouseMove(window, QPoint(20,distance));
- QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(20,distance));
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(20,distance));
// view should settle back at 0
QTRY_COMPARE(listview->contentY(), 0.0);
@@ -2271,18 +2323,18 @@ void tst_QQuickListView::sectionsDelegate_headerVisibility()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
window->requestActivate();
- QTest::qWaitForWindowActive(window.data());
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// ensure section header is maintained in view
listview->setCurrentIndex(20);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_VERIFY(qFuzzyCompare(listview->contentY(), 200.0));
QTRY_VERIFY(!listview->isMoving());
listview->setCurrentIndex(0);
@@ -2306,10 +2358,10 @@ void tst_QQuickListView::sectionsPositioning()
window->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart | QQuickViewSection::NextLabelAtEnd)));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
for (int i = 0; i < 3; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
@@ -2327,12 +2379,12 @@ void tst_QQuickListView::sectionsPositioning()
// move down a little and check that section header is at top
listview->setContentY(10);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QCOMPARE(topItem->y(), 0.);
// push the top header up
listview->setContentY(110);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
topItem = findVisibleChild(contentItem, "sect_0"); // section header
QVERIFY(topItem);
QCOMPARE(topItem->y(), 100.);
@@ -2347,13 +2399,13 @@ void tst_QQuickListView::sectionsPositioning()
// Move past section 0
listview->setContentY(120);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
topItem = findVisibleChild(contentItem, "sect_0"); // section header
QVERIFY(!topItem);
// Push section footer down
listview->setContentY(70);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
bottomItem = findVisibleChild(contentItem, "sect_4"); // section footer
QVERIFY(bottomItem);
QCOMPARE(bottomItem->y(), 380.);
@@ -2365,7 +2417,7 @@ void tst_QQuickListView::sectionsPositioning()
model.modifyItem(2, "Three", "aAa");
model.modifyItem(3, "Four", "aaA");
model.modifyItem(4, "Five", "Aaa");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->currentSection(), QString("aaa"));
@@ -2381,7 +2433,7 @@ void tst_QQuickListView::sectionsPositioning()
// remove section boundary
listview->setContentY(120);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
model.removeItem(5);
listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
@@ -2398,27 +2450,27 @@ void tst_QQuickListView::sectionsPositioning()
// Change the next section
listview->setContentY(0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
bottomItem = findVisibleChild(contentItem, "sect_3"); // section footer
QVERIFY(bottomItem);
QTRY_COMPARE(bottomItem->y(), 300.);
model.modifyItem(14, "New", "new");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_VERIFY(bottomItem = findVisibleChild(contentItem, "sect_new")); // section footer
QTRY_COMPARE(bottomItem->y(), 300.);
// delegate size increase should push section footer down
listview->setContentY(70);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_VERIFY(bottomItem = findVisibleChild(contentItem, "sect_3")); // section footer
QTRY_COMPARE(bottomItem->y(), 370.);
QQuickItem *inlineSection = findVisibleChild(contentItem, "sect_new");
item = findItem<QQuickItem>(contentItem, "wrapper", 13);
QVERIFY(item);
item->setHeight(40.);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(bottomItem->y(), 380.);
QCOMPARE(inlineSection->y(), 360.);
item->setHeight(20.);
@@ -2426,14 +2478,14 @@ void tst_QQuickListView::sectionsPositioning()
// Turn sticky footer off
listview->setContentY(20);
window->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart)));
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_VERIFY(item = findVisibleChild(contentItem, "sect_new")); // inline label restored
QCOMPARE(item->y(), 340.);
// Turn sticky header off
listview->setContentY(30);
window->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels)));
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_VERIFY(item = findVisibleChild(contentItem, "sect_aaa")); // inline label restored
QCOMPARE(item->y(), 0.);
@@ -2464,12 +2516,12 @@ void tst_QQuickListView::sectionPropertyChange()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
for (int i = 0; i < 2; ++i) {
@@ -2479,7 +2531,7 @@ void tst_QQuickListView::sectionPropertyChange()
}
QMetaObject::invokeMethod(window->rootObject(), "switchGroups");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
for (int i = 0; i < 2; ++i) {
@@ -2489,7 +2541,7 @@ void tst_QQuickListView::sectionPropertyChange()
}
QMetaObject::invokeMethod(window->rootObject(), "switchGroups");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
for (int i = 0; i < 2; ++i) {
@@ -2499,7 +2551,7 @@ void tst_QQuickListView::sectionPropertyChange()
}
QMetaObject::invokeMethod(window->rootObject(), "switchGrouped");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
for (int i = 0; i < 2; ++i) {
@@ -2509,7 +2561,7 @@ void tst_QQuickListView::sectionPropertyChange()
}
QMetaObject::invokeMethod(window->rootObject(), "switchGrouped");
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
for (int i = 0; i < 2; ++i) {
@@ -2528,12 +2580,12 @@ void tst_QQuickListView::sectionDelegateChange()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
- QQUICK_VERIFY_POLISH(listview);
+ QQuickTest::qWaitForItemPolished(listview);
QVERIFY(findItems<QQuickItem>(contentItem, "section1").count() > 0);
QCOMPARE(findItems<QQuickItem>(contentItem, "section2").count(), 0);
@@ -2545,7 +2597,7 @@ void tst_QQuickListView::sectionDelegateChange()
}
QMetaObject::invokeMethod(window->rootObject(), "switchDelegates");
- QQUICK_VERIFY_POLISH(listview);
+ QQuickTest::qWaitForItemPolished(listview);
QCOMPARE(findItems<QQuickItem>(contentItem, "section1").count(), 0);
QVERIFY(findItems<QQuickItem>(contentItem, "section2").count() > 0);
@@ -2574,10 +2626,10 @@ void tst_QQuickListView::sectionsItemInsertion()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
for (int i = 0; i < 3; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
@@ -2593,7 +2645,7 @@ void tst_QQuickListView::sectionsItemInsertion()
for (int i = 0; i < 10; i++)
model.insertItem(i, "Item" + QString::number(i), QLatin1String("A"));
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
QVERIFY(itemCount > 10);
@@ -2618,6 +2670,62 @@ void tst_QQuickListView::sectionsItemInsertion()
}
}
+void tst_QQuickListView::sectionsSnap_data()
+{
+ QTest::addColumn<QQuickListView::SnapMode>("snapMode");
+ QTest::addColumn<QPoint>("point");
+ QTest::addColumn<int>("duration");
+
+ QTest::newRow("drag") << QQuickListView::NoSnap << QPoint(100, 45) << 500;
+ QTest::newRow("flick") << QQuickListView::SnapOneItem << QPoint(100, 60) << 100;
+}
+
+void tst_QQuickListView::sectionsSnap()
+{
+ QFETCH(QQuickListView::SnapMode, snapMode);
+ QFETCH(QPoint, point);
+ QFETCH(int, duration);
+
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("sectionSnapping.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QTRY_VERIFY(listview != nullptr);
+ listview->setSnapMode(snapMode);
+
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_COMPARE(listview->currentIndex(), 0);
+ QCOMPARE(listview->contentY(), qreal(-50));
+
+ // move down
+ flick(window.data(), QPoint(100, 100), point, duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(0));
+
+ flick(window.data(), QPoint(100, 100), point, duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(50));
+
+ flick(window.data(), QPoint(100, 100), point, duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(150));
+
+ // move back up
+ flick(window.data(), point, QPoint(100, 100), duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(50));
+
+ flick(window.data(), point, QPoint(100, 100), duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(0));
+
+ flick(window.data(), point, QPoint(100, 100), duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(-50));
+}
+
void tst_QQuickListView::currentIndex_delayedItemCreation()
{
QFETCH(bool, setCurrentToZero);
@@ -2632,9 +2740,9 @@ void tst_QQuickListView::currentIndex_delayedItemCreation()
qApp->processEvents();
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QSignalSpy spy(listview, SIGNAL(currentItemChanged()));
//QCOMPARE(listview->currentIndex(), 0);
@@ -2659,7 +2767,7 @@ void tst_QQuickListView::currentIndex()
for (int i = 0; i < 30; i++)
initModel.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setGeometry(0,0,240,320);
QQmlContext *ctxt = window->rootContext();
@@ -2672,10 +2780,10 @@ void tst_QQuickListView::currentIndex()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// currentIndex is initialized to 20
// currentItem should be in view
@@ -2763,7 +2871,7 @@ void tst_QQuickListView::noCurrentIndex()
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setGeometry(0,0,240,320);
QQmlContext *ctxt = window->rootContext();
@@ -2775,10 +2883,10 @@ void tst_QQuickListView::noCurrentIndex()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// current index should be -1 at startup
// and we should not have a currentItem or highlightItem
@@ -2815,18 +2923,18 @@ void tst_QQuickListView::keyNavigation()
window->rootContext()->setContextProperty("testObject", testObject);
window->setSource(testFileUrl("listviewtest.qml"));
window->show();
- QTest::qWaitForWindowActive(window);
+ QVERIFY(QTest::qWaitForWindowActive(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setOrientation(orientation);
listview->setLayoutDirection(layoutDirection);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
window->requestActivate();
- QTest::qWaitForWindowActive(window);
+ QVERIFY(QTest::qWaitForWindowActive(window));
QTRY_COMPARE(qGuiApp->focusWindow(), window);
QTest::keyClick(window, forwardsKey);
@@ -2928,13 +3036,13 @@ void tst_QQuickListView::itemList()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "view");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
- QTRY_VERIFY(model != 0);
+ QTRY_VERIFY(model != nullptr);
QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
@@ -2967,13 +3075,13 @@ void tst_QQuickListView::itemListFlicker()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "view");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
- QTRY_VERIFY(model != 0);
+ QTRY_VERIFY(model != nullptr);
QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
@@ -3032,13 +3140,13 @@ void tst_QQuickListView::cacheBuffer()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_VERIFY(listview->delegate() != 0);
+ QTRY_VERIFY(contentItem != nullptr);
+ QTRY_VERIFY(listview->delegate() != nullptr);
QTRY_VERIFY(listview->model() != 0);
- QTRY_VERIFY(listview->highlight() != 0);
+ QTRY_VERIFY(listview->highlight() != nullptr);
// Confirm items positioned correctly
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -3057,8 +3165,8 @@ void tst_QQuickListView::cacheBuffer()
// items will be created one at a time
for (int i = itemCount; i < qMin(itemCount+10,model.count()); ++i) {
- QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == 0);
- QQuickItem *item = 0;
+ QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == nullptr);
+ QQuickItem *item = nullptr;
while (!item) {
bool b = false;
controller.incubateWhile(&b);
@@ -3092,11 +3200,11 @@ void tst_QQuickListView::cacheBuffer()
QCOMPARE(item->y(), qreal(i*20));
}
- QVERIFY(findItem<QQuickItem>(listview, "wrapper", 32) == 0);
+ QVERIFY(findItem<QQuickItem>(listview, "wrapper", 32) == nullptr);
// ensure buffered items are created
for (int i = 32; i < qMin(41,model.count()); ++i) {
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
while (!item) {
qGuiApp->processEvents(); // allow refill to happen
bool b = false;
@@ -3135,10 +3243,10 @@ void tst_QQuickListView::positionViewAtBeginningEnd()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
listview->setContentY(100);
@@ -3195,13 +3303,13 @@ void tst_QQuickListView::positionViewAtIndex()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
window->rootObject()->setProperty("enforceRange", enforceRange);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
listview->setContentY(initContentY);
@@ -3275,16 +3383,16 @@ void tst_QQuickListView::resetModel()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->count(), model.rowCount());
for (int i = 0; i < model.rowCount(); ++i) {
QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
- QTRY_VERIFY(display != 0);
+ QTRY_VERIFY(display != nullptr);
QTRY_COMPARE(display->text(), strings.at(i));
}
@@ -3297,7 +3405,7 @@ void tst_QQuickListView::resetModel()
for (int i = 0; i < model.rowCount(); ++i) {
QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
- QTRY_VERIFY(display != 0);
+ QTRY_VERIFY(display != nullptr);
QTRY_COMPARE(display->text(), strings.at(i));
}
}
@@ -3444,11 +3552,11 @@ void tst_QQuickListView::QTBUG_9791()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_VERIFY(listview->delegate() != 0);
+ QTRY_VERIFY(contentItem != nullptr);
+ QTRY_VERIFY(listview->delegate() != nullptr);
QTRY_VERIFY(listview->model() != 0);
QMetaObject::invokeMethod(listview, "fillModel");
@@ -3469,9 +3577,32 @@ void tst_QQuickListView::QTBUG_9791()
QTRY_COMPARE(listview->contentX(), 590.0);
}
+void tst_QQuickListView::QTBUG_33568()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("strictlyenforcerange-resize.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QVERIFY(listview != nullptr);
+
+ // we want to verify that the change animates smoothly, rather than jumping into place
+ QSignalSpy spy(listview, SIGNAL(contentYChanged()));
+
+ listview->incrementCurrentIndex();
+ QTRY_COMPARE(listview->contentY(), -100.0);
+ QVERIFY(spy.count() > 1);
+
+ spy.clear();
+ listview->incrementCurrentIndex();
+ QTRY_COMPARE(listview->contentY(), -50.0);
+ QVERIFY(spy.count() > 1);
+}
+
void tst_QQuickListView::manualHighlight()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setGeometry(0,0,240,320);
QString filename(testFile("manual-highlight.qml"));
@@ -3480,10 +3611,10 @@ void tst_QQuickListView::manualHighlight()
qApp->processEvents();
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QTRY_COMPARE(listview->currentIndex(), 0);
QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
@@ -3523,10 +3654,10 @@ void tst_QQuickListView::QTBUG_11105()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -3560,9 +3691,9 @@ void tst_QQuickListView::initialZValues()
qApp->processEvents();
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QVERIFY(listview->currentItem());
QTRY_COMPARE(listview->currentItem()->z(), listview->property("itemZ").toReal());
@@ -3576,7 +3707,7 @@ void tst_QQuickListView::initialZValues()
QVERIFY(listview->highlightItem());
QTRY_COMPARE(listview->highlightItem()->z(), listview->property("highlightZ").toReal());
- QQuickText *sectionItem = 0;
+ QQuickText *sectionItem = nullptr;
QTRY_VERIFY(sectionItem = findItem<QQuickText>(contentItem, "section"));
QTRY_COMPARE(sectionItem->z(), listview->property("sectionZ").toReal());
}
@@ -3614,16 +3745,16 @@ void tst_QQuickListView::header()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setOrientation(orientation);
listview->setLayoutDirection(layoutDirection);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
- QQuickText *header = 0;
+ QQuickText *header = nullptr;
QTRY_VERIFY(header = findItem<QQuickText>(contentItem, "header"));
QCOMPARE(header, listview->headerItem());
@@ -3693,11 +3824,11 @@ void tst_QQuickListView::header()
QVERIFY(QTest::qWaitForWindowExposed(window));
listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setOrientation(orientation);
listview->setLayoutDirection(layoutDirection);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
listview->setWidth(240);
listview->setHeight(320);
@@ -3780,10 +3911,10 @@ void tst_QQuickListView::header_delayItemCreation()
qApp->processEvents();
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickText *header = findItem<QQuickText>(contentItem, "header");
QVERIFY(header);
@@ -3803,13 +3934,13 @@ void tst_QQuickListView::headerChangesViewport()
window->setSource(testFileUrl("headerchangesviewport.qml"));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(listview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
- QQuickText *header = 0;
+ QQuickText *header = nullptr;
QTRY_VERIFY(header = findItem<QQuickText>(contentItem, "header"));
QCOMPARE(header, listview->headerItem());
@@ -3850,14 +3981,14 @@ void tst_QQuickListView::footer()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setOrientation(orientation);
listview->setLayoutDirection(layoutDirection);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
QVERIFY(footer);
@@ -4039,14 +4170,14 @@ void tst_QQuickListView::extents()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setOrientation(orientation);
listview->setLayoutDirection(layoutDirection);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
QVERIFY(header);
@@ -4137,10 +4268,10 @@ void tst_QQuickListView::resetModel_headerFooter()
qApp->processEvents();
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
QVERIFY(header);
@@ -4180,10 +4311,10 @@ void tst_QQuickListView::resizeView()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -4199,7 +4330,7 @@ void tst_QQuickListView::resizeView()
QCOMPARE(heightRatio.toReal(), 0.4);
listview->setHeight(200);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QMetaObject::invokeMethod(window->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
QCOMPARE(heightRatio.toReal(), 0.25);
@@ -4257,10 +4388,10 @@ void tst_QQuickListView::resizeViewAndRepaint()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// item at index 10 should not be currently visible
QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
@@ -4292,10 +4423,10 @@ void tst_QQuickListView::sizeLessThan1()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Confirm items positioned correctly
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -4316,10 +4447,10 @@ void tst_QQuickListView::QTBUG_14821()
qApp->processEvents();
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
listview->decrementCurrentIndex();
QCOMPARE(listview->currentIndex(), 99);
@@ -4344,20 +4475,20 @@ void tst_QQuickListView::resizeDelegate()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QCOMPARE(listview->count(), model.rowCount());
listview->setCurrentIndex(25);
listview->setContentY(0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
for (int i = 0; i < 16; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
+ QVERIFY(item != nullptr);
QCOMPARE(item->y(), i*20.0);
}
@@ -4365,11 +4496,11 @@ void tst_QQuickListView::resizeDelegate()
QTRY_COMPARE(listview->highlightItem()->y(), 500.0);
window->rootObject()->setProperty("delegateHeight", 30);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
for (int i = 0; i < 11; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
+ QVERIFY(item != nullptr);
QTRY_COMPARE(item->y(), i*30.0);
}
@@ -4379,11 +4510,11 @@ void tst_QQuickListView::resizeDelegate()
listview->setCurrentIndex(1);
listview->positionViewAtIndex(25, QQuickListView::Beginning);
listview->positionViewAtIndex(5, QQuickListView::Beginning);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
for (int i = 5; i < 16; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
+ QVERIFY(item != nullptr);
QCOMPARE(item->y(), i*30.0);
}
@@ -4391,11 +4522,11 @@ void tst_QQuickListView::resizeDelegate()
QTRY_COMPARE(listview->highlightItem()->y(), 30.0);
window->rootObject()->setProperty("delegateHeight", 20);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
for (int i = 5; i < 11; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
+ QVERIFY(item != nullptr);
QTRY_COMPARE(item->y(), 150 + (i-5)*20.0);
}
@@ -4425,15 +4556,15 @@ void tst_QQuickListView::resizeFirstDelegate()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
for (int i = 0; i < model.count(); ++i) {
item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
+ QVERIFY(item != nullptr);
QCOMPARE(item->y(), i*20.0);
}
@@ -4448,7 +4579,7 @@ void tst_QQuickListView::resizeFirstDelegate()
for (int i = 1; i < model.count(); ++i) {
item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QVERIFY(item != 0);
+ QVERIFY(item != nullptr);
QTRY_COMPARE(item->y(), (i-1)*20.0);
}
@@ -4467,7 +4598,7 @@ void tst_QQuickListView::resizeFirstDelegate()
listview->setCurrentIndex(19);
qApp->processEvents();
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// items 0-2 should have been deleted
for (int i=0; i<3; i++) {
@@ -4497,8 +4628,8 @@ void tst_QQuickListView::repositionResizedDelegate()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QTRY_VERIFY(listview != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(listview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *positioner = findItem<QQuickItem>(window->rootObject(), "positioner");
QVERIFY(positioner);
@@ -4513,7 +4644,7 @@ void tst_QQuickListView::repositionResizedDelegate()
listview->setContentX(contentPos_itemFirstHalfVisible.x());
listview->setContentY(contentPos_itemFirstHalfVisible.y());
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
prevSpyCount = spy.count();
QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "incrementRepeater"));
QTRY_COMPARE(positioner->boundingRect().size(), resizedPositionerRect.size());
@@ -4530,7 +4661,7 @@ void tst_QQuickListView::repositionResizedDelegate()
listview->setContentX(contentPos_itemSecondHalfVisible.x());
listview->setContentY(contentPos_itemSecondHalfVisible.y());
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
prevSpyCount = spy.count();
QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "incrementRepeater"));
@@ -4589,7 +4720,7 @@ void tst_QQuickListView::QTBUG_16037()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "listview");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QVERIFY(listview->contentHeight() <= 0.0);
@@ -4634,13 +4765,13 @@ void tst_QQuickListView::indexAt_itemAt()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
if (index >= 0) {
item = findItem<QQuickItem>(contentItem, "wrapper", index);
QVERIFY(item);
@@ -4652,32 +4783,50 @@ void tst_QQuickListView::indexAt_itemAt()
delete testObject;
}
+void tst_QQuickListView::itemAtIndex()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("listview-itematindex.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QVERIFY(listview != nullptr);
+
+ QCOMPARE(listview->itemAtIndex(-1), nullptr);
+ QCOMPARE(listview->itemAtIndex(3), nullptr);
+ QQuickItem *item = listview->itemAtIndex(0);
+ QVERIFY(item);
+ QCOMPARE(item->property("idx"), 0);
+ item = listview->itemAtIndex(1);
+ QVERIFY(item);
+ QCOMPARE(item->property("idx"), 1);
+ item = listview->itemAtIndex(2);
+ QVERIFY(item);
+ QCOMPARE(item->property("idx"), 2);
+}
+
void tst_QQuickListView::incrementalModel()
{
QScopedPointer<QQuickView> window(createView());
- QSKIP("QTBUG-30716");
IncrementalModel model;
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
window->setSource(testFileUrl("displaylist.qml"));
- qApp->processEvents();
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- listview->forceLayout();
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
-
- listview->forceLayout();
- QTRY_COMPARE(listview->count(), 20);
+ QTRY_VERIFY(contentItem != nullptr);
+ QTRY_COMPARE(listview->count(), 35);
listview->positionViewAtIndex(10, QQuickListView::Beginning);
-
- listview->forceLayout();
- QTRY_COMPARE(listview->count(), 25);
+ QTRY_COMPARE(listview->count(), 45);
}
void tst_QQuickListView::onAdd()
@@ -4794,17 +4943,17 @@ void tst_QQuickListView::rightToLeft()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "view");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
- QTRY_VERIFY(model != 0);
+ QTRY_VERIFY(model != nullptr);
QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
@@ -4843,12 +4992,12 @@ void tst_QQuickListView::test_mirroring()
QScopedPointer<QQuickView> windowA(createView());
windowA->setSource(testFileUrl("rightToLeft.qml"));
QQuickListView *listviewA = findItem<QQuickListView>(windowA->rootObject(), "view");
- QTRY_VERIFY(listviewA != 0);
+ QTRY_VERIFY(listviewA != nullptr);
QScopedPointer<QQuickView> windowB(createView());
windowB->setSource(testFileUrl("rightToLeft.qml"));
QQuickListView *listviewB = findItem<QQuickListView>(windowB->rootObject(), "view");
- QTRY_VERIFY(listviewA != 0);
+ QTRY_VERIFY(listviewA != nullptr);
qApp->processEvents();
QList<QString> objectNames;
@@ -4911,10 +5060,10 @@ void tst_QQuickListView::margins()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QCOMPARE(listview->contentY(), -30.);
QCOMPARE(listview->originY(), 0.);
@@ -4923,7 +5072,7 @@ void tst_QQuickListView::margins()
listview->positionViewAtEnd();
qreal pos = listview->contentY();
listview->setContentY(pos + 80);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
listview->returnToBounds();
QTRY_COMPARE(listview->contentY(), pos + 50);
@@ -4934,7 +5083,7 @@ void tst_QQuickListView::margins()
listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
listview->setContentY(-50);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
listview->returnToBounds();
QCOMPARE(listview->originY(), 20.);
QTRY_COMPARE(listview->contentY(), -10.);
@@ -4982,12 +5131,12 @@ void tst_QQuickListView::marginsResize()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "listview");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setOrientation(orientation);
listview->setLayoutDirection(layoutDirection);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// view is resized after componentCompleted - top margin should still be visible
if (orientation == QQuickListView::Vertical)
@@ -5121,16 +5270,16 @@ void tst_QQuickListView::snapToItem()
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setOrientation(orientation);
listview->setLayoutDirection(layoutDirection);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
listview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
// confirm that a flick hits an item boundary
flick(window, flickStart, flickEnd, 180);
@@ -5168,6 +5317,31 @@ void tst_QQuickListView::snapToItem()
releaseView(window);
}
+void tst_QQuickListView::snapToItemWithSpacing_QTBUG_59852()
+{
+ QQuickView *window = getView();
+
+ window->setSource(testFileUrl("snapToItemWithSpacing.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ auto *listView = qobject_cast<QQuickListView*>(window->rootObject());
+ QVERIFY(listView);
+
+ QVERIFY(QQuickTest::qWaitForItemPolished(listView));
+
+ // each item in the list is 100 pixels tall, and the spacing is 100
+
+ listView->setContentY(110); // this is right below the first item
+ listView->returnToBounds();
+ QCOMPARE(listView->contentY(), 200); // the position of the second item
+
+ listView->setContentY(60); // this is right below the middle of the first item
+ listView->returnToBounds();
+ QCOMPARE(listView->contentY(), 0); // it's farther to go to the next item, so snaps to the first
+
+ releaseView(window);
+}
void tst_QQuickListView::snapOneItemResize_QTBUG_43555()
{
@@ -5181,18 +5355,18 @@ void tst_QQuickListView::snapOneItemResize_QTBUG_43555()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QSignalSpy currentIndexSpy(listview, SIGNAL(currentIndexChanged()));
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->currentIndex(), 5);
currentIndexSpy.clear();
window->resize(QSize(400, 320));
QTRY_COMPARE(int(listview->width()), 400);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->currentIndex(), 5);
QCOMPARE(currentIndexSpy.count(), 0);
@@ -5384,7 +5558,7 @@ void tst_QQuickListView::asynchronous()
QQuickItem *rootObject = qobject_cast<QQuickItem*>(window->rootObject());
QVERIFY(rootObject);
- QQuickListView *listview = 0;
+ QQuickListView *listview = nullptr;
while (!listview) {
bool b = false;
controller.incubateWhile(&b);
@@ -5393,8 +5567,8 @@ void tst_QQuickListView::asynchronous()
// items will be created one at a time
for (int i = 0; i < 8; ++i) {
- QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == 0);
- QQuickItem *item = 0;
+ QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == nullptr);
+ QQuickItem *item = nullptr;
while (!item) {
bool b = false;
controller.incubateWhile(&b);
@@ -5426,38 +5600,50 @@ void tst_QQuickListView::snapOneItem_data()
QTest::addColumn<qreal>("snapAlignment");
QTest::addColumn<qreal>("endExtent");
QTest::addColumn<qreal>("startExtent");
+ QTest::addColumn<qreal>("flickSlowdown");
QTest::newRow("vertical, top to bottom")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 560.0 << 0.0;
+ << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 560.0 << 0.0 << 1.0;
QTest::newRow("vertical, bottom to top")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 20) << QPoint(20, 200) << -420.0 << -560.0 - 240.0 << -240.0;
+ << QPoint(20, 20) << QPoint(20, 200) << -420.0 << -560.0 - 240.0 << -240.0 << 1.0;
QTest::newRow("horizontal, left to right")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::NoHighlightRange)
- << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 560.0 << 0.0;
+ << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 560.0 << 0.0 << 1.0;
QTest::newRow("horizontal, right to left")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom << int(QQuickItemView::NoHighlightRange)
- << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -560.0 - 240.0 << -240.0;
+ << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -560.0 - 240.0 << -240.0 << 1.0;
QTest::newRow("vertical, top to bottom, enforce range")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 580.0 << -20.0;
+ << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 580.0 << -20.0 << 1.0;
QTest::newRow("vertical, bottom to top, enforce range")
<< QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::BottomToTop << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 20) << QPoint(20, 200) << -420.0 << -580.0 - 240.0 << -220.0;
+ << QPoint(20, 20) << QPoint(20, 200) << -420.0 << -580.0 - 240.0 << -220.0 << 1.0;
QTest::newRow("horizontal, left to right, enforce range")
<< QQuickListView::Horizontal << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 580.0 << -20.0;
+ << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 580.0 << -20.0 << 1.0;
QTest::newRow("horizontal, right to left, enforce range")
<< QQuickListView::Horizontal << Qt::RightToLeft << QQuickItemView::TopToBottom << int(QQuickItemView::StrictlyEnforceRange)
- << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -580.0 - 240.0 << -220.0;
+ << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -580.0 - 240.0 << -220.0 << 1.0;
+
+ // Using e.g. 120 rather than 95 always went to the next item.
+ // Ensure this further movement has the same behavior
+ QTest::newRow("vertical, top to bottom, no more blindspot")
+ << QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::NoHighlightRange)
+ << QPoint(20, 200) << QPoint(20, 95) << 180.0 << 560.0 << 0.0 << 6.0;
+
+ // StrictlyEnforceRange should not override valid SnapOneItem decisions
+ QTest::newRow("vertical, top to bottom, no more blindspot, enforce range")
+ << QQuickListView::Vertical << Qt::LeftToRight << QQuickItemView::TopToBottom << int(QQuickItemView::StrictlyEnforceRange)
+ << QPoint(20, 200) << QPoint(20, 95) << 180.0 << 580.0 << -20.0 << 6.0;
}
void tst_QQuickListView::snapOneItem()
@@ -5471,6 +5657,9 @@ void tst_QQuickListView::snapOneItem()
QFETCH(qreal, snapAlignment);
QFETCH(qreal, endExtent);
QFETCH(qreal, startExtent);
+ QFETCH(qreal, flickSlowdown);
+
+ qreal flickDuration = 180 * flickSlowdown;
QQuickView *window = getView();
QQuickViewTestUtil::moveMouseAway(window);
@@ -5481,21 +5670,21 @@ void tst_QQuickListView::snapOneItem()
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->setOrientation(orientation);
listview->setLayoutDirection(layoutDirection);
listview->setVerticalLayoutDirection(verticalLayoutDirection);
listview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
+ QTRY_VERIFY(contentItem != nullptr);
QSignalSpy currentIndexSpy(listview, SIGNAL(currentIndexChanged()));
// confirm that a flick hits the next item boundary
- flick(window, flickStart, flickEnd, 180);
+ flick(window, flickStart, flickEnd, flickDuration);
QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
if (orientation == QQuickListView::Vertical)
QCOMPARE(listview->contentY(), snapAlignment);
@@ -5509,7 +5698,7 @@ void tst_QQuickListView::snapOneItem()
// flick to end
do {
- flick(window, flickStart, flickEnd, 180);
+ flick(window, flickStart, flickEnd, flickDuration);
QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
} while (orientation == QQuickListView::Vertical
? verticalLayoutDirection == QQuickItemView::TopToBottom ? !listview->isAtYEnd() : !listview->isAtYBeginning()
@@ -5527,7 +5716,7 @@ void tst_QQuickListView::snapOneItem()
// flick to start
do {
- flick(window, flickEnd, flickStart, 180);
+ flick(window, flickEnd, flickStart, flickDuration);
QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
} while (orientation == QQuickListView::Vertical
? verticalLayoutDirection == QQuickItemView::TopToBottom ? !listview->isAtYBeginning() : !listview->isAtYEnd()
@@ -5554,21 +5743,39 @@ void tst_QQuickListView::snapOneItemCurrentIndexRemoveAnimation()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QTRY_COMPARE(listview->currentIndex(), 0);
QSignalSpy currentIndexSpy(listview, SIGNAL(currentIndexChanged()));
QMetaObject::invokeMethod(window->rootObject(), "removeItemZero");
QTRY_COMPARE(listview->property("transitionsRun").toInt(), 1);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QCOMPARE(listview->currentIndex(), 0);
QCOMPARE(currentIndexSpy.count(), 0);
}
+void tst_QQuickListView::snapOneItemWrongDirection()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("snapOneItemWrongDirection.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QTRY_VERIFY(listview != nullptr);
+
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
+ QTRY_COMPARE(listview->currentIndex(), 0);
+
+ listview->flick(0,500);
+ QTRY_VERIFY(!listview->isMovingHorizontally());
+ QCOMPARE(listview->contentX(), qreal(0));
+}
+
void tst_QQuickListView::attachedProperties_QTBUG_32836()
{
QScopedPointer<QQuickView> window(createView());
@@ -5577,7 +5784,7 @@ void tst_QQuickListView::attachedProperties_QTBUG_32836()
qApp->processEvents();
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *header = listview->headerItem();
QVERIFY(header);
@@ -5606,7 +5813,7 @@ void tst_QQuickListView::unrequestedVisibility()
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), QString::number(i));
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setGeometry(0,0,240,320);
QQmlContext *ctxt = window->rootContext();
@@ -5711,7 +5918,7 @@ void tst_QQuickListView::unrequestedVisibility()
QCOMPARE(delegateVisible(item), false);
model.moveItems(19, 1, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
QTRY_VERIFY((item = findItem<QQuickItem>(leftContent, wrapperObjectName, 1)));
QCOMPARE(delegateVisible(item), false);
@@ -5740,7 +5947,7 @@ void tst_QQuickListView::unrequestedVisibility()
QCOMPARE(delegateVisible(item), false);
model.moveItems(3, 4, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
@@ -5756,7 +5963,7 @@ void tst_QQuickListView::unrequestedVisibility()
QCOMPARE(delegateVisible(item), false);
model.moveItems(4, 3, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
@@ -5772,7 +5979,7 @@ void tst_QQuickListView::unrequestedVisibility()
QCOMPARE(delegateVisible(item), false);
model.moveItems(16, 17, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
@@ -5788,7 +5995,7 @@ void tst_QQuickListView::unrequestedVisibility()
QCOMPARE(delegateVisible(item), false);
model.moveItems(17, 16, 1);
- QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(leftview));
item = findItem<QQuickItem>(leftContent, wrapperObjectName, 4);
QVERIFY(item);
@@ -5848,7 +6055,7 @@ void tst_QQuickListView::populateTransitions()
QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), 0);
QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 16);
} else {
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QCOMPARE(listview->property("countPopulateTransitions").toInt(), 0);
QCOMPARE(listview->property("countAddTransitions").toInt(), 0);
}
@@ -5860,7 +6067,7 @@ void tst_QQuickListView::populateTransitions()
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -5895,7 +6102,7 @@ void tst_QQuickListView::populateTransitions()
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -5913,7 +6120,7 @@ void tst_QQuickListView::populateTransitions()
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -5958,8 +6165,8 @@ void tst_QQuickListView::sizeTransitions()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(listview != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// the following will start the transition
model.addItem(QLatin1String("Test"), "");
@@ -6021,14 +6228,14 @@ void tst_QQuickListView::addTransitions()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
if (contentY != 0) {
listview->setContentY(contentY);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
}
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
@@ -6102,7 +6309,7 @@ void tst_QQuickListView::addTransitions()
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -6217,14 +6424,14 @@ void tst_QQuickListView::moveTransitions()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickText *name;
if (contentY != 0) {
listview->setContentY(contentY);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
}
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
@@ -6287,7 +6494,7 @@ void tst_QQuickListView::moveTransitions()
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -6420,14 +6627,14 @@ void tst_QQuickListView::removeTransitions()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
if (contentY != 0) {
listview->setContentY(contentY);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
}
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
@@ -6501,7 +6708,7 @@ void tst_QQuickListView::removeTransitions()
QCOMPARE(item->x(), 0.0);
QCOMPARE(item->y(), contentY + (i-firstVisibleIndex) * 20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -6632,10 +6839,10 @@ void tst_QQuickListView::displacedTransitions()
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
listview->setProperty("displaceTransitionsDone", false);
@@ -6656,7 +6863,7 @@ void tst_QQuickListView::displacedTransitions()
break;
case ListChange::Moved:
model.moveItems(change.index, change.to, change.count);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
break;
case ListChange::SetCurrent:
case ListChange::SetContentY:
@@ -6716,7 +6923,7 @@ void tst_QQuickListView::displacedTransitions()
QCOMPARE(item->x(), 0.0);
QCOMPARE(item->y(), i * 20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -6852,14 +7059,14 @@ void tst_QQuickListView::multipleTransitions()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
if (contentY != 0) {
listview->setContentY(contentY);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
}
int timeBetweenActions = window->rootObject()->property("timeBetweenActions").toInt();
@@ -6893,7 +7100,7 @@ void tst_QQuickListView::multipleTransitions()
break;
case ListChange::Moved:
model.moveItems(changes[i].index, changes[i].to, changes[i].count);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
if (i == changes.count() - 1) {
QTRY_VERIFY(!listview->property("runningMoveTargets").toBool());
QTRY_VERIFY(!listview->property("runningMoveDisplaced").toBool());
@@ -6906,7 +7113,7 @@ void tst_QQuickListView::multipleTransitions()
break;
case ListChange::SetContentY:
listview->setContentY(changes[i].pos);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
break;
case ListChange::Polish:
break;
@@ -6924,7 +7131,7 @@ void tst_QQuickListView::multipleTransitions()
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -7009,10 +7216,10 @@ void tst_QQuickListView::multipleDisplaced()
QVERIFY(QTest::qWaitForWindowExposed(window));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
model.moveItems(12, 8, 1);
QTest::qWait(window->rootObject()->property("duration").toInt() / 2);
@@ -7033,7 +7240,7 @@ void tst_QQuickListView::multipleDisplaced()
QTRY_COMPARE(item->x(), 0.0);
QTRY_COMPARE(item->y(), i*20.0);
QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model.name(i));
}
@@ -7102,11 +7309,11 @@ void tst_QQuickListView::flickBeyondBounds()
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QTRY_VERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_VERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
// Flick view up beyond bounds
flick(window.data(), QPoint(10, 10), QPoint(10, -2000), 180);
@@ -7214,11 +7421,11 @@ void tst_QQuickListView::destroyItemOnCreation()
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QCOMPARE(window->rootObject()->property("createdIndex").toInt(), -1);
model.addItem("new item", "");
@@ -7235,14 +7442,14 @@ void tst_QQuickListView::parentBinding()
window->setSource(testFileUrl("parentBinding.qml"));
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QVERIFY(contentItem != nullptr);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
QVERIFY(item);
@@ -7271,7 +7478,7 @@ void tst_QQuickListView::accessEmptyCurrentItem_QTBUG_30227()
window->setSource(testFileUrl("emptymodel.qml"));
QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
listview->forceLayout();
QMetaObject::invokeMethod(window->rootObject(), "remove");
@@ -7287,7 +7494,7 @@ void tst_QQuickListView::delayedChanges_QTBUG_30555()
window->setSource(testFileUrl("delayedChanges.qml"));
QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QCOMPARE(listview->count(), 10);
@@ -7306,7 +7513,7 @@ void tst_QQuickListView::outsideViewportChangeNotAffectingView()
window->setSource(testFileUrl("outsideViewportChangeNotAffectingView.qml"));
QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -7340,7 +7547,7 @@ void tst_QQuickListView::testProxyModelChangedAfterMove()
window->setSource(testFileUrl("proxytest.qml"));
QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -7360,7 +7567,7 @@ void tst_QQuickListView::typedModel()
QCOMPARE(listview->count(), 6);
- QQmlListModel *listModel = 0;
+ QQmlListModel *listModel = nullptr;
listview->setModel(QVariant::fromValue(listModel));
QCOMPARE(listview->count(), 0);
@@ -7374,10 +7581,10 @@ void tst_QQuickListView::displayMargin()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *content = listview->contentItem();
- QVERIFY(content != 0);
+ QVERIFY(content != nullptr);
QQuickItem *item0 = findItem<QQuickItem>(content, "delegate", 0);
QVERIFY(item0);
@@ -7390,7 +7597,7 @@ void tst_QQuickListView::displayMargin()
QCOMPARE(delegateVisible(item14), true);
// the 15th item should be outside the end margin
- QVERIFY(findItem<QQuickItem>(content, "delegate", 14) == 0);
+ QVERIFY(findItem<QQuickItem>(content, "delegate", 14) == nullptr);
// the first delegate should still be within the begin margin
listview->positionViewAtIndex(3, QQuickListView::Beginning);
@@ -7410,13 +7617,13 @@ void tst_QQuickListView::negativeDisplayMargin()
QQuickItem *listview = window->rootObject();
QQuickListView *innerList = findItem<QQuickListView>(window->rootObject(), "innerList");
- QVERIFY(innerList != 0);
+ QVERIFY(innerList != nullptr);
QTRY_COMPARE(innerList->property("createdItems").toInt(), 11);
QCOMPARE(innerList->property("destroyedItem").toInt(), 0);
QQuickItem *content = innerList->contentItem();
- QVERIFY(content != 0);
+ QVERIFY(content != nullptr);
QQuickItem *item = findItem<QQuickItem>(content, "delegate", 0);
QVERIFY(item);
@@ -7483,7 +7690,7 @@ void tst_QQuickListView::QTBUG_35920()
QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject());
QVERIFY(listview);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(10,0));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(10,0));
for (int i = 0; i < 100; ++i) {
QTest::mouseMove(window.data(), QPoint(10,i));
if (listview->isMoving()) {
@@ -7500,7 +7707,7 @@ void tst_QQuickListView::QTBUG_35920()
QCOMPARE(listview->contentY(), contentY);
}
}
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(10,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(10,100));
}
Q_DECLARE_METATYPE(Qt::Orientation)
@@ -7934,12 +8141,12 @@ void tst_QQuickListView::roundingErrors()
// QTBUG-37339: drag an item and verify that it doesn't
// get prematurely released due to rounding errors
- QTest::mousePress(window.data(), Qt::LeftButton, 0, viewPos);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, viewPos);
for (int i = 0; i < 150; i += 5) {
QTest::mouseMove(window.data(), viewPos - QPoint(i, 0));
QVERIFY(item);
}
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(0, 36));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(0, 36));
// maintain position relative to the right edge
listview->setLayoutDirection(Qt::RightToLeft);
@@ -8044,6 +8251,35 @@ void tst_QQuickListView::programmaticFlickAtBounds2()
QTRY_COMPARE(listview->contentY(), qreal(100.0));
}
+void tst_QQuickListView::programmaticFlickAtBounds3()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("programmaticFlickAtBounds3.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject());
+ QVERIFY(listview);
+
+ // flick down
+ listview->flick(0, 2000);
+
+ // verify scope of the movement
+ QTRY_VERIFY(listview->property("minOvershoot").toReal() < qreal(-50.0));
+
+ // reset, and test a second time
+ listview->cancelFlick();
+ listview->returnToBounds();
+ QTRY_COMPARE(listview->contentY(), qreal(0.0));
+ listview->setProperty("minOvershoot", qreal(0.0));
+
+ // flick down
+ listview->flick(0, 2000);
+
+ // verify scope of the movement is the same
+ QTRY_VERIFY(listview->property("minOvershoot").toReal() < qreal(-50.0));
+}
+
void tst_QQuickListView::layoutChange()
{
RandomSortModel *model = new RandomSortModel;
@@ -8291,7 +8527,7 @@ void tst_QQuickListView::contentHeightWithDelayRemove()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
const int initialCount(listview->count());
const int eventualCount(initialCount + countDelta);
@@ -8320,7 +8556,7 @@ void tst_QQuickListView::QTBUG_48044_currentItemNotVisibleAfterTransition()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
// Expand 2nd header
listview->setProperty("transitionsDone", QVariant(false));
@@ -8413,6 +8649,49 @@ void tst_QQuickListView::keyNavigationEnabled()
QCOMPARE(listView->currentIndex(), 1);
}
+void tst_QQuickListView::QTBUG_61269_appendDuringScrollDown_data()
+{
+ QTest::addColumn<QQuickListView::SnapMode>("snapMode");
+
+ QTest::newRow("NoSnap") << QQuickListView::NoSnap;
+ QTest::newRow("SnapToItem") << QQuickListView::SnapToItem;
+ QTest::newRow("SnapOneItem") << QQuickListView::SnapOneItem;
+}
+
+void tst_QQuickListView::QTBUG_61269_appendDuringScrollDown() // AKA QTBUG-62864
+{
+ QFETCH(QQuickListView::SnapMode, snapMode);
+
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("appendDuringScrollDown.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+
+ QQuickListView *listView = qobject_cast<QQuickListView *>(window->rootObject());
+ listView->setSnapMode(snapMode);
+ QQuickItem *highlightItem = listView->highlightItem();
+ QVERIFY(listView);
+ QCOMPARE(listView->isKeyNavigationEnabled(), true);
+ listView->setHighlightMoveVelocity(400);
+ listView->setHighlightMoveDuration(-1); // let it animate
+ listView->setFocus(true);
+ QVERIFY(listView->hasActiveFocus());
+ qreal highlightYLimit = listView->height() - highlightItem->height(); // should be 200
+
+ for (int i = 1; i < 15; ++i) {
+ QTest::keyClick(window.data(), Qt::Key_Down);
+
+ // Wait for the highlight movement animation to finish.
+ QTRY_COMPARE(highlightItem->y(), 40.0 * i);
+
+ // As we scroll down, the QML will append rows to its own model.
+ // Make sure the highlighted row and highlight item stay within the view.
+ // In QTBUG-62864 and QTBUG-61269, it would go off the bottom.
+ QVERIFY(highlightItem->y() - listView->contentY() <= highlightYLimit);
+ }
+}
+
void tst_QQuickListView::QTBUG_48870_fastModelUpdates()
{
StressTestModel model;
@@ -8426,11 +8705,11 @@ void tst_QQuickListView::QTBUG_48870_fastModelUpdates()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
- QTRY_VERIFY(listview != 0);
+ QTRY_VERIFY(listview != nullptr);
QQuickItemViewPrivate *priv = QQuickItemViewPrivate::get(listview);
bool nonUnique;
- FxViewItem *item = Q_NULLPTR;
+ FxViewItem *item = nullptr;
int expectedIdx;
QVERIFY(testVisibleItems(priv, &nonUnique, &item, &expectedIdx));
@@ -8469,7 +8748,7 @@ void tst_QQuickListView::QTBUG_50097_stickyHeader_positionViewAtIndex()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QTRY_COMPARE(listview->contentY(), -100.0); // the header size, since the header is overlaid
listview->setProperty("currentPage", 2);
QTRY_COMPARE(listview->contentY(), 400.0); // a full page of items down, sans the original negative header position
@@ -8477,6 +8756,46 @@ void tst_QQuickListView::QTBUG_50097_stickyHeader_positionViewAtIndex()
QTRY_COMPARE(listview->contentY(), -100.0); // back to the same position: header visible, items not under the header.
}
+void tst_QQuickListView::QTBUG_63974_stickyHeader_positionViewAtIndex_Contain()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("qtbug63974.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QVERIFY(listview != nullptr);
+
+ const qreal headerSize = 20;
+ const qreal footerSize = 20;
+ const qreal itemSize = 20;
+ const int itemCount = 30;
+ const qreal contentHeight = itemCount * itemSize;
+
+ const qreal initialY = listview->contentY();
+ const qreal endPosition = contentHeight + footerSize - listview->height();
+
+ QVERIFY(qFuzzyCompare(initialY, -headerSize));
+
+ listview->positionViewAtIndex(itemCount - 1, QQuickListView::Contain);
+ QTRY_COMPARE(listview->contentY(), endPosition);
+
+ listview->positionViewAtIndex(0, QQuickListView::Contain);
+ QTRY_COMPARE(listview->contentY(), -headerSize);
+
+ listview->positionViewAtIndex(itemCount - 1, QQuickListView::Visible);
+ QTRY_COMPARE(listview->contentY(), endPosition);
+
+ listview->positionViewAtIndex(0, QQuickListView::Visible);
+ QTRY_COMPARE(listview->contentY(), -headerSize);
+
+ listview->positionViewAtIndex(itemCount - 1, QQuickListView::SnapPosition);
+ QTRY_COMPARE(listview->contentY(), endPosition);
+
+ listview->positionViewAtIndex(0, QQuickListView::SnapPosition);
+ QTRY_COMPARE(listview->contentY(), -headerSize);
+}
+
void tst_QQuickListView::itemFiltered()
{
QStringListModel model(QStringList() << "one" << "two" << "three" << "four" << "five" << "six");
@@ -8502,12 +8821,153 @@ void tst_QQuickListView::itemFiltered()
window->setContent(QUrl(), &component, component.create());
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
// this should not crash
model.setData(model.index(2), QStringLiteral("modified three"), Qt::DisplayRole);
}
+void tst_QQuickListView::releaseItems()
+{
+ QScopedPointer<QQuickView> view(createView());
+ view->setSource(testFileUrl("releaseItems.qml"));
+
+ QQuickListView *listview = qobject_cast<QQuickListView *>(view->rootObject());
+ QVERIFY(listview);
+
+ // don't crash (QTBUG-61294)
+ listview->setModel(123);
+}
+
+void tst_QQuickListView::QTBUG_34576_velocityZero()
+{
+ QQuickView *window = new QQuickView(nullptr);
+ window->setGeometry(0,0,240,320);
+
+ QString filename(testFile("qtbug34576.qml"));
+ window->setSource(QUrl::fromLocalFile(filename));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QVERIFY(listview);
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listview));
+
+ QSignalSpy horizontalVelocitySpy(listview, SIGNAL(horizontalVelocityChanged()));
+
+ // currentIndex is initialized to 0
+ QCOMPARE(listview->currentIndex(), 0);
+
+ // set currentIndex to last item currently visible item
+ window->rootObject()->setProperty("horizontalVelocityZeroCount", QVariant(0));
+ listview->setCurrentIndex(2);
+ QTRY_COMPARE(window->rootObject()->property("current").toInt(), 2);
+ QCOMPARE(horizontalVelocitySpy.count(), 0);
+ QCOMPARE(window->rootObject()->property("horizontalVelocityZeroCount").toInt(), 0);
+
+ QSignalSpy currentIndexChangedSpy(listview, SIGNAL(currentIndexChanged()));
+
+ // click button which increases currentIndex
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(295,215));
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(295,215));
+
+ // verify that currentIndexChanged is triggered
+ QTRY_VERIFY(currentIndexChangedSpy.count() > 0);
+
+ // since we have set currentIndex to an item out of view, the listview will scroll
+ QTRY_COMPARE(window->rootObject()->property("current").toInt(), 3);
+ QTRY_VERIFY(horizontalVelocitySpy.count() > 0);
+
+ // velocity should be always > 0.0
+ QTRY_COMPARE(window->rootObject()->property("horizontalVelocityZeroCount").toInt(), 0);
+
+ delete window;
+}
+
+void tst_QQuickListView::QTBUG_61537_modelChangesAsync()
+{
+ // The purpose of this test if to check that any model changes that happens
+ // during start-up, while a loader higher up in the chain is still incubating
+ // async, will not fail.
+ QQuickView window;
+ window.setGeometry(0,0,640,480);
+
+ QString filename(testFile("qtbug61537_modelChangesAsync.qml"));
+ window.setSource(QUrl::fromLocalFile(filename));
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ // The qml file will assign the listview to the 'listView' property once the
+ // loader is ready with async incubation. So we need to wait for it.
+ QObject *root = window.rootObject();
+ QTRY_VERIFY(root->property("listView").value<QQuickListView *>());
+ QQuickListView *listView = root->property("listView").value<QQuickListView *>();
+ QVERIFY(listView);
+
+ // Check that the number of delegates we expect to be visible in
+ // the listview matches the number of items we find if we count.
+ int reportedCount = listView->count();
+ int actualCount = findItems<QQuickItem>(listView, "delegate").count();
+ QCOMPARE(reportedCount, actualCount);
+}
+
+void tst_QQuickListView::addOnCompleted()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("addoncompleted.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "view");
+ QTRY_VERIFY(listview != nullptr);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != nullptr);
+
+ qreal y = -1;
+ for (char name = 'a'; name <= 'j'; ++name) {
+ for (int num = 9; num >= 0; --num) {
+ const QString objName = QString::fromLatin1("%1%2").arg(name).arg(num);
+ QQuickItem *item = findItem<QQuickItem>(contentItem, objName);
+ if (!item) {
+ QVERIFY(name >= 'd');
+ y = 9999999;
+ } else {
+ const qreal newY = item->y();
+ QVERIFY2(newY > y, objName.toUtf8().constData());
+ y = newY;
+ }
+ }
+ }
+}
+
+void tst_QQuickListView::setPositionOnLayout()
+{
+ // Make sure we don't trigger a crash by removing items during layout from setPosition().
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("setpositiononlayout.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ for (int i = 0; i < 1000; ++i) {
+ QTest::keyPress(window.data(), Qt::Key_Down);
+ QTest::qWait(1);
+ QTest::keyRelease(window.data(), Qt::Key_Down);
+ }
+}
+
+void tst_QQuickListView::useDelegateChooserWithoutDefault()
+{
+ // Check that the application doesn't crash
+ // if the delegate chooser doesn't cover all cells
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("usechooserwithoutdefault.qml"));
+ window->show();
+};
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickloader/BLACKLIST b/tests/auto/quick/qquickloader/BLACKLIST
new file mode 100644
index 0000000000..a45a300607
--- /dev/null
+++ b/tests/auto/quick/qquickloader/BLACKLIST
@@ -0,0 +1,4 @@
+# Test fails on qemu when bound to one core, passes on real ARM
+# QTBUG-63049
+[asyncToSync1]
+b2qt
diff --git a/tests/auto/quick/qquickloader/data/bindings.qml b/tests/auto/quick/qquickloader/data/bindings.qml
new file mode 100644
index 0000000000..e0eae2a3e5
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/bindings.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ property alias game: theGame
+ property alias loader: theLoader
+
+ Item {
+ id: theGame
+
+ property bool isReady: false
+
+ onStateChanged: {
+ if (state == "invalid") {
+ // The Loader's active property is bound to isReady, so none of its bindings
+ // should be updated when isReady becomes false
+ isReady = false;
+
+ player.destroy();
+ player = null;
+ } else if (state == "running") {
+ player = Qt.createQmlObject("import QtQuick 2.0; Item { property color color: 'black' }", root);
+
+ isReady = true;
+ }
+ }
+
+ property Item player
+ }
+
+ Loader {
+ id: theLoader
+ active: theGame.isReady
+ sourceComponent: Rectangle {
+ width: 400
+ height: 400
+ color: game.player.color
+
+ property var game: theGame
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml b/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml
new file mode 100644
index 0000000000..d4c5daecab
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+import QtQuick.Window 2.1
+
+Item {
+ width: 400
+ height: 400
+ objectName: "root Item"
+
+ Loader {
+ sourceComponent: Rectangle {
+ objectName: "yellow rectangle"
+ x: 50; y: 50; width: 300; height: 300
+ color: "yellow"
+ Window {
+ objectName: "red transient Window"
+ width: 100
+ height: 100
+ visible: true // makes it harder, because it wants to become visible before root has a window
+ color: "red"
+ title: "red"
+ flags: Qt.Dialog
+ onVisibilityChanged: console.log("visibility " + visibility)
+ onVisibleChanged: console.log("visible " + visible)
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml b/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml
new file mode 100644
index 0000000000..69421448e0
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.0
+import QtQuick.Window 2.1
+
+Item {
+ width: 400
+ height: 400
+ objectName: "root Item"
+
+ Loader {
+ sourceComponent: Window {
+ objectName: "red transient Window"
+ width: 100
+ height: 100
+ visible: true // makes it harder, because it wants to become visible before root has a window
+ color: "red"
+ title: "red"
+ flags: Qt.Dialog
+ onVisibilityChanged: console.log("visibility " + visibility)
+ onVisibleChanged: console.log("visible " + visible)
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickloader/data/parentErrors.qml b/tests/auto/quick/qquickloader/data/parentErrors.qml
new file mode 100644
index 0000000000..36607e7f05
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/parentErrors.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 360
+ height: 360
+
+ property alias loader: loader
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ }
+
+ property Component component: Rectangle {
+ width: parent.width
+ height: parent.height
+ color: "pink"
+ }
+}
diff --git a/tests/auto/quick/qquickloader/data/rootContext.qml b/tests/auto/quick/qquickloader/data/rootContext.qml
new file mode 100644
index 0000000000..277db43d57
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/rootContext.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 360
+ height: 360
+
+ property alias loader: loader
+
+ Loader {
+ id: loader
+ }
+
+ property Component component: Item {
+ property bool trigger: false
+ onTriggerChanged: {
+ objectInRootContext.doIt() // make sure we can resolve objectInRootContext
+ loader.active = false
+ objectInRootContext.doIt() // make sure we can STILL resolve objectInRootContext
+ anotherProperty = true // see if we can trigger subsequent signal handlers (we shouldn't)
+ }
+ property bool anotherProperty: false
+ onAnotherPropertyChanged: {
+ // this should never be executed
+ objectInRootContext.doIt()
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickloader/qquickloader.pro b/tests/auto/quick/qquickloader/qquickloader.pro
index 32350388e8..c754c78bec 100644
--- a/tests/auto/quick/qquickloader/qquickloader.pro
+++ b/tests/auto/quick/qquickloader/qquickloader.pro
@@ -2,13 +2,13 @@ CONFIG += testcase
TARGET = tst_qquickloader
macx:CONFIG -= app_bundle
-INCLUDEPATH += ../../shared/
HEADERS += ../../shared/testhttpserver.h
SOURCES += tst_qquickloader.cpp \
../../shared/testhttpserver.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
TESTDATA = data/*
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 3e7439f3e9..fbdd87905b 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -29,12 +29,18 @@
#include <QSignalSpy>
+#include <QtQml/QQmlContext>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlincubator.h>
+#include <QtQuick/qquickview.h>
#include <private/qquickloader_p.h>
+#include <private/qquickwindowmodule_p.h>
#include "testhttpserver.h"
#include "../../shared/util.h"
+#include "../shared/geometrytestutil.h"
+
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
class SlowComponent : public QQmlComponent
{
@@ -49,11 +55,11 @@ class PeriodicIncubationController : public QObject,
public QQmlIncubationController
{
public:
- PeriodicIncubationController() : incubated(false) {}
+ PeriodicIncubationController() {}
void start() { startTimer(20); }
- bool incubated;
+ bool incubated = false;
protected:
virtual void timerEvent(QTimerEvent *) {
@@ -74,8 +80,6 @@ public:
tst_QQuickLoader();
private slots:
- void cleanup();
-
void sourceOrComponent();
void sourceOrComponent_data();
void clear();
@@ -113,22 +117,25 @@ private slots:
void parented();
void sizeBound();
void QTBUG_30183();
+ void transientWindow();
+ void nestedTransientWindow();
void sourceComponentGarbageCollection();
-private:
- QQmlEngine engine;
+ void bindings();
+ void parentErrors();
+
+ void rootContext();
+ void sourceURLKeepComponent();
+
};
-void tst_QQuickLoader::cleanup()
-{
- // clear components. otherwise we even bypass the test server by using the cache.
- engine.clearComponentCache();
-}
+Q_DECLARE_METATYPE(QList<QQmlError>)
tst_QQuickLoader::tst_QQuickLoader()
{
qmlRegisterType<SlowComponent>("LoaderTest", 1, 0, "SlowComponent");
+ qRegisterMetaType<QList<QQmlError>>();
}
void tst_QQuickLoader::sourceOrComponent()
@@ -142,6 +149,7 @@ void tst_QQuickLoader::sourceOrComponent()
if (error)
QTest::ignoreMessage(QtWarningMsg, errorString.toUtf8().constData());
+ QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray(
"import QtQuick 2.0\n"
@@ -163,14 +171,14 @@ void tst_QQuickLoader::sourceOrComponent()
"}")
, dataDirectoryUrl());
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
- QCOMPARE(loader->item() == 0, error);
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ QVERIFY(loader != nullptr);
+ QCOMPARE(loader->item() == nullptr, error);
QCOMPARE(loader->source(), sourceUrl);
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->status(), error ? QQuickLoader::Error : QQuickLoader::Ready);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), error ? 0: 1);
+ QCOMPARE(static_cast<QQuickItem*>(loader.data())->childItems().count(), error ? 0: 1);
if (!error) {
bool sourceComponentIsChildOfLoader = false;
@@ -195,8 +203,6 @@ void tst_QQuickLoader::sourceOrComponent()
QCOMPARE(loader->property("onItemChangedCount").toInt(), 1);
QCOMPARE(loader->property("onLoadedCount").toInt(), error ? 0 : 1);
-
- delete loader;
}
void tst_QQuickLoader::sourceOrComponent_data()
@@ -218,6 +224,8 @@ void tst_QQuickLoader::sourceOrComponent_data()
void tst_QQuickLoader::clear()
{
+ QQmlEngine engine;
+
{
QQmlComponent component(&engine);
component.setData(QByteArray(
@@ -227,22 +235,20 @@ void tst_QQuickLoader::clear()
" Timer { interval: 200; running: true; onTriggered: loader.source = '' }\n"
" }")
, dataDirectoryUrl());
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ QVERIFY(loader != nullptr);
QVERIFY(loader->item());
QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+ QCOMPARE(static_cast<QQuickItem*>(loader.data())->childItems().count(), 1);
QTRY_VERIFY(!loader->item());
QCOMPARE(loader->progress(), 0.0);
QCOMPARE(loader->status(), QQuickLoader::Null);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- delete loader;
+ QCOMPARE(static_cast<QQuickItem*>(loader.data())->childItems().count(), 0);
}
{
QQmlComponent component(&engine, testFileUrl("/SetSourceComponent.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(item);
QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
@@ -251,18 +257,16 @@ void tst_QQuickLoader::clear()
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
- loader->setSourceComponent(0);
+ loader->setSourceComponent(nullptr);
QVERIFY(!loader->item());
QCOMPARE(loader->progress(), 0.0);
QCOMPARE(loader->status(), QQuickLoader::Null);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- delete item;
}
{
QQmlComponent component(&engine, testFileUrl("/SetSourceComponent.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(item);
QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
@@ -271,19 +275,18 @@ void tst_QQuickLoader::clear()
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
- QMetaObject::invokeMethod(item, "clear");
+ QMetaObject::invokeMethod(item.data(), "clear");
QVERIFY(!loader->item());
QCOMPARE(loader->progress(), 0.0);
QCOMPARE(loader->status(), QQuickLoader::Null);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- delete item;
}
}
void tst_QQuickLoader::urlToComponent()
{
+ QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQuick 2.0\n"
"Loader {\n"
@@ -293,22 +296,21 @@ void tst_QQuickLoader::urlToComponent()
" Timer { interval: 100; running: true; onTriggered: loader.sourceComponent = myComp }\n"
"}" )
, dataDirectoryUrl());
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
QTest::qWait(200);
- QTRY_VERIFY(loader != 0);
+ QTRY_VERIFY(loader != nullptr);
QVERIFY(loader->item());
QCOMPARE(loader->progress(), 1.0);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+ QCOMPARE(static_cast<QQuickItem*>(loader.data())->childItems().count(), 1);
QCOMPARE(loader->width(), 10.0);
QCOMPARE(loader->height(), 10.0);
-
- delete loader;
}
void tst_QQuickLoader::componentToUrl()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("/SetSourceComponent.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(item);
QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
@@ -323,20 +325,19 @@ void tst_QQuickLoader::componentToUrl()
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
QCOMPARE(loader->width(), 120.0);
QCOMPARE(loader->height(), 60.0);
-
- delete item;
}
void tst_QQuickLoader::anchoredLoader()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("/AnchoredLoader.qml"));
- QQuickItem *rootItem = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(rootItem != 0);
+ QScopedPointer<QQuickItem> rootItem(qobject_cast<QQuickItem*>(component.create()));
+ QVERIFY(rootItem != nullptr);
QQuickItem *loader = rootItem->findChild<QQuickItem*>("loader");
QQuickItem *sourceElement = rootItem->findChild<QQuickItem*>("sourceElement");
- QVERIFY(loader != 0);
- QVERIFY(sourceElement != 0);
+ QVERIFY(loader != nullptr);
+ QVERIFY(sourceElement != nullptr);
QCOMPARE(rootItem->width(), 300.0);
QCOMPARE(rootItem->height(), 200.0);
@@ -350,9 +351,10 @@ void tst_QQuickLoader::anchoredLoader()
void tst_QQuickLoader::sizeLoaderToItem()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("/SizeToItem.qml"));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ QVERIFY(loader != nullptr);
QCOMPARE(loader->width(), 120.0);
QCOMPARE(loader->height(), 60.0);
@@ -385,15 +387,14 @@ void tst_QQuickLoader::sizeLoaderToItem()
loader->setHeight(30);
QCOMPARE(rect->width(), 180.0);
QCOMPARE(rect->height(), 30.0);
-
- delete loader;
}
void tst_QQuickLoader::sizeItemToLoader()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("/SizeToLoader.qml"));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ QVERIFY(loader != nullptr);
QCOMPARE(loader->width(), 200.0);
QCOMPARE(loader->height(), 80.0);
@@ -403,10 +404,16 @@ void tst_QQuickLoader::sizeItemToLoader()
QCOMPARE(rect->height(), 80.0);
// Check resize
- loader->setWidth(180);
- loader->setHeight(30);
- QCOMPARE(rect->width(), 180.0);
- QCOMPARE(rect->height(), 30.0);
+ QSizeChangeListener sizeListener(rect);
+ const QSizeF size(180, 30);
+ loader->setSize(size);
+ QVERIFY2(!sizeListener.isEmpty(), "There should be at least one signal about the size changed");
+ for (const QSizeF sizeOnGeometryChanged : sizeListener) {
+ // Check that we have the correct size on all signals
+ QCOMPARE(sizeOnGeometryChanged, size);
+ }
+ QCOMPARE(rect->width(), size.width());
+ QCOMPARE(rect->height(), size.height());
// Switch mode
loader->resetWidth(); // reset explicit size
@@ -415,41 +422,37 @@ void tst_QQuickLoader::sizeItemToLoader()
rect->setHeight(45);
QCOMPARE(loader->width(), 160.0);
QCOMPARE(loader->height(), 45.0);
-
- delete loader;
}
void tst_QQuickLoader::noResize()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("/NoResize.qml"));
- QQuickItem* item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != 0);
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
+ QVERIFY(item != nullptr);
QCOMPARE(item->width(), 200.0);
QCOMPARE(item->height(), 80.0);
-
- delete item;
}
void tst_QQuickLoader::networkRequestUrl()
{
ThreadedTestHTTPServer server(dataDirectory());
+ QQmlEngine engine;
QQmlComponent component(&engine);
const QString qml = "import QtQuick 2.0\nLoader { property int signalCount : 0; source: \"" + server.baseUrl().toString() + "/Rect120x60.qml\"; onLoaded: signalCount += 1 }";
component.setData(qml.toUtf8(), testFileUrl("../dummy.qml"));
if (component.isError())
qDebug() << component.errors();
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ QVERIFY(loader != nullptr);
QTRY_COMPARE(loader->status(), QQuickLoader::Ready);
QVERIFY(loader->item());
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->property("signalCount").toInt(), 1);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- delete loader;
+ QCOMPARE(static_cast<QQuickItem*>(loader.data())->childItems().count(), 1);
}
/* XXX Component waits until all dependencies are loaded. Is this actually possible? */
@@ -457,6 +460,7 @@ void tst_QQuickLoader::networkComponent()
{
ThreadedTestHTTPServer server(dataDirectory(), TestHTTPServer::Delay);
+ QQmlEngine engine;
QQmlComponent component(&engine);
const QString qml = "import QtQuick 2.0\n"
"import \"" + server.baseUrl().toString() + "/\" as NW\n"
@@ -489,117 +493,108 @@ void tst_QQuickLoader::failNetworkRequest()
QTest::ignoreMessage(QtWarningMsg, QString(server.baseUrl().toString() + "/IDontExist.qml: File not found").toUtf8());
+ QQmlEngine engine;
QQmlComponent component(&engine);
const QString qml = "import QtQuick 2.0\nLoader { property int did_load: 123; source: \"" + server.baseUrl().toString() + "/IDontExist.qml\"; onLoaded: did_load=456 }";
component.setData(qml.toUtf8(), server.url("/dummy.qml"));
QTRY_COMPARE(component.status(), QQmlComponent::Ready);
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ QVERIFY(loader != nullptr);
QTRY_COMPARE(loader->status(), QQuickLoader::Error);
QVERIFY(!loader->item());
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->property("did_load").toInt(), 123);
- QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
-
- delete loader;
+ QCOMPARE(static_cast<QQuickItem*>(loader.data())->childItems().count(), 0);
}
void tst_QQuickLoader::active()
{
+ QQmlEngine engine;
+
// check that the item isn't instantiated until active is set to true
{
QQmlComponent component(&engine, testFileUrl("active.1.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
QVERIFY(loader->active() == false); // set manually to false
QVERIFY(!loader->item());
- QMetaObject::invokeMethod(object, "doSetSourceComponent");
+ QMetaObject::invokeMethod(object.data(), "doSetSourceComponent");
QVERIFY(!loader->item());
- QMetaObject::invokeMethod(object, "doSetSource");
+ QMetaObject::invokeMethod(object.data(), "doSetSource");
QVERIFY(!loader->item());
- QMetaObject::invokeMethod(object, "doSetActive");
- QVERIFY(loader->item() != 0);
-
- delete object;
+ QMetaObject::invokeMethod(object.data(), "doSetActive");
+ QVERIFY(loader->item() != nullptr);
}
// check that the status is Null if active is set to false
{
QQmlComponent component(&engine, testFileUrl("active.2.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
QVERIFY(loader->active() == true); // active is true by default
QCOMPARE(loader->status(), QQuickLoader::Ready);
int currStatusChangedCount = loader->property("statusChangedCount").toInt();
- QMetaObject::invokeMethod(object, "doSetInactive");
+ QMetaObject::invokeMethod(object.data(), "doSetInactive");
QCOMPARE(loader->status(), QQuickLoader::Null);
QCOMPARE(loader->property("statusChangedCount").toInt(), (currStatusChangedCount+1));
-
- delete object;
}
// check that the source is not cleared if active is set to false
{
QQmlComponent component(&engine, testFileUrl("active.3.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
QVERIFY(loader->active() == true); // active is true by default
QVERIFY(!loader->source().isEmpty());
int currSourceChangedCount = loader->property("sourceChangedCount").toInt();
- QMetaObject::invokeMethod(object, "doSetInactive");
+ QMetaObject::invokeMethod(object.data(), "doSetInactive");
QVERIFY(!loader->source().isEmpty());
QCOMPARE(loader->property("sourceChangedCount").toInt(), currSourceChangedCount);
-
- delete object;
}
// check that the sourceComponent is not cleared if active is set to false
{
QQmlComponent component(&engine, testFileUrl("active.4.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
QVERIFY(loader->active() == true); // active is true by default
- QVERIFY(loader->sourceComponent() != 0);
+ QVERIFY(loader->sourceComponent() != nullptr);
int currSourceComponentChangedCount = loader->property("sourceComponentChangedCount").toInt();
- QMetaObject::invokeMethod(object, "doSetInactive");
- QVERIFY(loader->sourceComponent() != 0);
+ QMetaObject::invokeMethod(object.data(), "doSetInactive");
+ QVERIFY(loader->sourceComponent() != nullptr);
QCOMPARE(loader->property("sourceComponentChangedCount").toInt(), currSourceComponentChangedCount);
-
- delete object;
}
// check that the item is released if active is set to false
{
QQmlComponent component(&engine, testFileUrl("active.5.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
QVERIFY(loader->active() == true); // active is true by default
- QVERIFY(loader->item() != 0);
+ QVERIFY(loader->item() != nullptr);
int currItemChangedCount = loader->property("itemChangedCount").toInt();
- QMetaObject::invokeMethod(object, "doSetInactive");
+ QMetaObject::invokeMethod(object.data(), "doSetInactive");
QVERIFY(!loader->item());
QCOMPARE(loader->property("itemChangedCount").toInt(), (currItemChangedCount+1));
-
- delete object;
}
// check that the activeChanged signal is emitted correctly
{
QQmlComponent component(&engine, testFileUrl("active.6.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
QVERIFY(loader->active() == true); // active is true by default
@@ -613,34 +608,30 @@ void tst_QQuickLoader::active()
QCOMPARE(loader->property("activeChangedCount").toInt(), 2);
loader->setActive(false); // change signal should be emitted
QCOMPARE(loader->property("activeChangedCount").toInt(), 3);
- QMetaObject::invokeMethod(object, "doSetActive");
+ QMetaObject::invokeMethod(object.data(), "doSetActive");
QCOMPARE(loader->property("activeChangedCount").toInt(), 4);
- QMetaObject::invokeMethod(object, "doSetActive");
+ QMetaObject::invokeMethod(object.data(), "doSetActive");
QCOMPARE(loader->property("activeChangedCount").toInt(), 4);
- QMetaObject::invokeMethod(object, "doSetInactive");
+ QMetaObject::invokeMethod(object.data(), "doSetInactive");
QCOMPARE(loader->property("activeChangedCount").toInt(), 5);
loader->setActive(true); // change signal should be emitted
QCOMPARE(loader->property("activeChangedCount").toInt(), 6);
-
- delete object;
}
// check that the component isn't loaded until active is set to true
{
QQmlComponent component(&engine, testFileUrl("active.7.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QCOMPARE(object->property("success").toBool(), true);
- delete object;
}
// check that the component is loaded if active is not set (true by default)
{
QQmlComponent component(&engine, testFileUrl("active.8.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QCOMPARE(object->property("success").toBool(), true);
- delete object;
}
}
@@ -704,14 +695,15 @@ void tst_QQuickLoader::initialPropertyValues()
foreach (const QString &warning, expectedWarnings)
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
+ QQmlEngine engine;
QQmlComponent component(&engine, qmlFile);
- QObject *object = component.beginCreate(engine.rootContext());
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
+ QVERIFY(object != nullptr);
const int serverBaseUrlPropertyIndex = object->metaObject()->indexOfProperty("serverBaseUrl");
if (serverBaseUrlPropertyIndex != -1) {
QMetaProperty prop = object->metaObject()->property(serverBaseUrlPropertyIndex);
- QVERIFY(prop.write(object, server.baseUrl().toString()));
+ QVERIFY(prop.write(object.data(), server.baseUrl().toString()));
}
component.completeCreate();
@@ -722,20 +714,17 @@ void tst_QQuickLoader::initialPropertyValues()
for (int i = 0; i < propertyNames.size(); ++i)
QCOMPARE(object->property(propertyNames.at(i).toLatin1().constData()), propertyValues.at(i));
-
- delete object;
}
void tst_QQuickLoader::initialPropertyValuesBinding()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("initialPropertyValues.binding.qml"));
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QVERIFY(object->setProperty("bindable", QVariant(8)));
QCOMPARE(object->property("canaryValue").toInt(), 8);
-
- delete object;
}
void tst_QQuickLoader::initialPropertyValuesError_data()
@@ -750,7 +739,7 @@ void tst_QQuickLoader::initialPropertyValuesError_data()
<< (QStringList() << QString(testFileUrl("NonexistentSourceComponent.qml").toString() + ": No such file or directory"));
QTest::newRow("invalid source url") << testFileUrl("initialPropertyValues.error.3.qml")
- << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
+ << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Expected token `:'"));
QTest::newRow("invalid initial property values object with invalid property access") << testFileUrl("initialPropertyValues.error.4.qml")
<< (QStringList() << QString(testFileUrl("initialPropertyValues.error.4.qml").toString() + ":7:5: QML Loader: setSource: value is not an object")
@@ -765,23 +754,24 @@ void tst_QQuickLoader::initialPropertyValuesError()
foreach (const QString &warning, expectedWarnings)
QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
+ QQmlEngine engine;
QQmlComponent component(&engine, qmlFile);
- QObject *object = component.create();
- QVERIFY(object != 0);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
- QVERIFY(loader != 0);
+ QVERIFY(loader != nullptr);
QVERIFY(!loader->item());
- delete object;
}
// QTBUG-9241
void tst_QQuickLoader::deleteComponentCrash()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("crash.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(item);
- item->metaObject()->invokeMethod(item, "setLoaderSource");
+ item->metaObject()->invokeMethod(item.data(), "setLoaderSource");
QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
QVERIFY(loader);
@@ -789,73 +779,68 @@ void tst_QQuickLoader::deleteComponentCrash()
QCOMPARE(loader->item()->objectName(), QLatin1String("blue"));
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->status(), QQuickLoader::Ready);
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
QTRY_COMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
QCOMPARE(loader->source(), testFileUrl("BlueRect.qml"));
-
- delete item;
}
void tst_QQuickLoader::nonItem()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("nonItem.qml"));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
QVERIFY(loader);
QVERIFY(loader->item());
- QCOMPARE(loader, loader->item()->parent());
+ QCOMPARE(loader.data(), loader->item()->parent());
QPointer<QObject> item = loader->item();
loader->setActive(false);
QVERIFY(!loader->item());
QTRY_VERIFY(!item);
-
- delete loader;
}
void tst_QQuickLoader::vmeErrors()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("vmeErrors.qml"));
QString err = testFileUrl("VmeError.qml").toString() + ":6:26: Cannot assign object type QObject with no default method";
QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
QVERIFY(loader);
QVERIFY(!loader->item());
-
- delete loader;
}
// QTBUG-13481
void tst_QQuickLoader::creationContext()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("creationContext.qml"));
- QObject *o = component.create();
- QVERIFY(o != 0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o != nullptr);
QCOMPARE(o->property("test").toBool(), true);
-
- delete o;
}
void tst_QQuickLoader::QTBUG_16928()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("QTBUG_16928.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(item);
QCOMPARE(item->width(), 250.);
QCOMPARE(item->height(), 250.);
-
- delete item;
}
void tst_QQuickLoader::implicitSize()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("implicitSize.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(item);
QCOMPARE(item->width(), 150.);
@@ -868,27 +853,24 @@ void tst_QQuickLoader::implicitSize()
QSignalSpy implWidthSpy(loader, SIGNAL(implicitWidthChanged()));
QSignalSpy implHeightSpy(loader, SIGNAL(implicitHeightChanged()));
- QMetaObject::invokeMethod(item, "changeImplicitSize");
+ QMetaObject::invokeMethod(item.data(), "changeImplicitSize");
QCOMPARE(loader->property("implicitWidth").toReal(), 200.);
QCOMPARE(loader->property("implicitHeight").toReal(), 300.);
QCOMPARE(implWidthSpy.count(), 1);
QCOMPARE(implHeightSpy.count(), 1);
-
- delete item;
}
void tst_QQuickLoader::QTBUG_17114()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("QTBUG_17114.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(item);
QCOMPARE(item->property("loaderWidth").toReal(), 32.);
QCOMPARE(item->property("loaderHeight").toReal(), 32.);
-
- delete item;
}
void tst_QQuickLoader::asynchronous_data()
@@ -903,7 +885,7 @@ void tst_QQuickLoader::asynchronous_data()
<< (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": No such file or directory"));
QTest::newRow("Invalid component") << testFileUrl("InvalidSourceComponent.qml")
- << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
+ << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Expected token `:'"));
}
void tst_QQuickLoader::asynchronous()
@@ -911,13 +893,14 @@ void tst_QQuickLoader::asynchronous()
QFETCH(QUrl, qmlFile);
QFETCH(QStringList, expectedWarnings);
+ QQmlEngine engine;
PeriodicIncubationController *controller = new PeriodicIncubationController;
QQmlIncubationController *previous = engine.incubationController();
engine.setIncubationController(controller);
delete previous;
QQmlComponent component(&engine, testFileUrl("asynchronous.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(root);
QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
@@ -929,7 +912,7 @@ void tst_QQuickLoader::asynchronous()
QVERIFY(!loader->item());
QCOMPARE(loader->progress(), 0.0);
root->setProperty("comp", qmlFile.toString());
- QMetaObject::invokeMethod(root, "loadComponent");
+ QMetaObject::invokeMethod(root.data(), "loadComponent");
QVERIFY(!loader->item());
if (expectedWarnings.isEmpty()) {
@@ -945,19 +928,18 @@ void tst_QQuickLoader::asynchronous()
QTRY_COMPARE(loader->progress(), 1.0);
QTRY_COMPARE(loader->status(), QQuickLoader::Error);
}
-
- delete root;
}
void tst_QQuickLoader::asynchronous_clear()
{
+ QQmlEngine engine;
PeriodicIncubationController *controller = new PeriodicIncubationController;
QQmlIncubationController *previous = engine.incubationController();
engine.setIncubationController(controller);
delete previous;
QQmlComponent component(&engine, testFileUrl("asynchronous.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(root);
QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
@@ -965,7 +947,7 @@ void tst_QQuickLoader::asynchronous_clear()
QVERIFY(!loader->item());
root->setProperty("comp", "BigComponent.qml");
- QMetaObject::invokeMethod(root, "loadComponent");
+ QMetaObject::invokeMethod(root.data(), "loadComponent");
QVERIFY(!loader->item());
controller->start();
@@ -974,7 +956,7 @@ void tst_QQuickLoader::asynchronous_clear()
// clear before component created
root->setProperty("comp", "");
- QMetaObject::invokeMethod(root, "loadComponent");
+ QMetaObject::invokeMethod(root.data(), "loadComponent");
QVERIFY(!loader->item());
QCOMPARE(engine.incubationController()->incubatingObjectCount(), 0);
@@ -984,7 +966,7 @@ void tst_QQuickLoader::asynchronous_clear()
// check loading component
root->setProperty("comp", "BigComponent.qml");
- QMetaObject::invokeMethod(root, "loadComponent");
+ QMetaObject::invokeMethod(root.data(), "loadComponent");
QVERIFY(!loader->item());
QCOMPARE(loader->status(), QQuickLoader::Loading);
@@ -994,19 +976,18 @@ void tst_QQuickLoader::asynchronous_clear()
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->status(), QQuickLoader::Ready);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- delete root;
}
void tst_QQuickLoader::simultaneousSyncAsync()
{
+ QQmlEngine engine;
PeriodicIncubationController *controller = new PeriodicIncubationController;
QQmlIncubationController *previous = engine.incubationController();
engine.setIncubationController(controller);
delete previous;
QQmlComponent component(&engine, testFileUrl("simultaneous.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(root);
QQuickLoader *asyncLoader = root->findChild<QQuickLoader*>("asyncLoader");
@@ -1016,7 +997,7 @@ void tst_QQuickLoader::simultaneousSyncAsync()
QVERIFY(!asyncLoader->item());
QVERIFY(!syncLoader->item());
- QMetaObject::invokeMethod(root, "loadComponents");
+ QMetaObject::invokeMethod(root.data(), "loadComponents");
QVERIFY(!asyncLoader->item());
QVERIFY(syncLoader->item());
@@ -1027,8 +1008,6 @@ void tst_QQuickLoader::simultaneousSyncAsync()
QTRY_VERIFY(asyncLoader->item());
QCOMPARE(asyncLoader->progress(), 1.0);
QCOMPARE(asyncLoader->status(), QQuickLoader::Ready);
-
- delete root;
}
void tst_QQuickLoader::asyncToSync1()
@@ -1040,7 +1019,7 @@ void tst_QQuickLoader::asyncToSync1()
delete previous;
QQmlComponent component(&engine, testFileUrl("asynchronous.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(root);
QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
@@ -1048,7 +1027,7 @@ void tst_QQuickLoader::asyncToSync1()
QVERIFY(!loader->item());
root->setProperty("comp", "BigComponent.qml");
- QMetaObject::invokeMethod(root, "loadComponent");
+ QMetaObject::invokeMethod(root.data(), "loadComponent");
QVERIFY(!loader->item());
controller->start();
@@ -1061,19 +1040,18 @@ void tst_QQuickLoader::asyncToSync1()
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->status(), QQuickLoader::Ready);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- delete root;
}
void tst_QQuickLoader::asyncToSync2()
{
+ QQmlEngine engine;
PeriodicIncubationController *controller = new PeriodicIncubationController;
QQmlIncubationController *previous = engine.incubationController();
engine.setIncubationController(controller);
delete previous;
QQmlComponent component(&engine, testFileUrl("asynchronous.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(root);
QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
@@ -1081,7 +1059,7 @@ void tst_QQuickLoader::asyncToSync2()
QVERIFY(!loader->item());
root->setProperty("comp", "BigComponent.qml");
- QMetaObject::invokeMethod(root, "loadComponent");
+ QMetaObject::invokeMethod(root.data(), "loadComponent");
QVERIFY(!loader->item());
controller->start();
@@ -1094,12 +1072,11 @@ void tst_QQuickLoader::asyncToSync2()
QCOMPARE(loader->progress(), 1.0);
QCOMPARE(loader->status(), QQuickLoader::Ready);
QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
-
- delete root;
}
void tst_QQuickLoader::loadedSignal()
{
+ QQmlEngine engine;
PeriodicIncubationController *controller = new PeriodicIncubationController;
QQmlIncubationController *previous = engine.incubationController();
engine.setIncubationController(controller);
@@ -1110,84 +1087,79 @@ void tst_QQuickLoader::loadedSignal()
// and then immediately setting active to false, causes the
// loader to be deactivated, including disabling the incubator.
QQmlComponent component(&engine, testFileUrl("loadedSignal.qml"));
- QObject *obj = component.create();
+ QScopedPointer<QObject> obj(component.create());
- QMetaObject::invokeMethod(obj, "triggerLoading");
+ QMetaObject::invokeMethod(obj.data(), "triggerLoading");
QTest::qWait(100); // ensure that loading would have finished if it wasn't deactivated
QCOMPARE(obj->property("loadCount").toInt(), 0);
QVERIFY(obj->property("success").toBool());
- QMetaObject::invokeMethod(obj, "triggerLoading");
+ QMetaObject::invokeMethod(obj.data(), "triggerLoading");
QTest::qWait(100);
QCOMPARE(obj->property("loadCount").toInt(), 0);
QVERIFY(obj->property("success").toBool());
- QMetaObject::invokeMethod(obj, "triggerMultipleLoad");
+ QMetaObject::invokeMethod(obj.data(), "triggerMultipleLoad");
controller->start();
QTest::qWait(100);
QTRY_COMPARE(obj->property("loadCount").toInt(), 1); // only one loaded signal should be emitted.
QVERIFY(obj->property("success").toBool());
-
- delete obj;
}
{
// ensure that an error doesn't result in the onLoaded signal being emitted.
QQmlComponent component(&engine, testFileUrl("loadedSignal.2.qml"));
- QObject *obj = component.create();
+ QScopedPointer<QObject> obj(component.create());
- QMetaObject::invokeMethod(obj, "triggerLoading");
+ QMetaObject::invokeMethod(obj.data(), "triggerLoading");
QTest::qWait(100);
QCOMPARE(obj->property("loadCount").toInt(), 0);
QVERIFY(obj->property("success").toBool());
-
- delete obj;
}
}
void tst_QQuickLoader::parented()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("parented.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(root);
QQuickItem *item = root->findChild<QQuickItem*>("comp");
QVERIFY(item);
- QCOMPARE(item->parentItem(), root);
+ QCOMPARE(item->parentItem(), root.data());
QCOMPARE(item->width(), 300.);
QCOMPARE(item->height(), 300.);
-
- delete root;
}
void tst_QQuickLoader::sizeBound()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("sizebound.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
+ QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
QVERIFY(root);
QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
- QVERIFY(loader != 0);
+ QVERIFY(loader != nullptr);
QVERIFY(loader->item());
QCOMPARE(loader->width(), 50.0);
QCOMPARE(loader->height(), 60.0);
- QMetaObject::invokeMethod(root, "switchComponent");
+ QMetaObject::invokeMethod(root.data(), "switchComponent");
QCOMPARE(loader->width(), 80.0);
QCOMPARE(loader->height(), 90.0);
-
- delete root;
}
void tst_QQuickLoader::QTBUG_30183()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("/QTBUG_30183.qml"));
- QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
- QVERIFY(loader != 0);
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ QVERIFY(loader != nullptr);
QCOMPARE(loader->width(), 240.0);
QCOMPARE(loader->height(), 120.0);
@@ -1196,19 +1168,98 @@ void tst_QQuickLoader::QTBUG_30183()
QVERIFY(rect);
QCOMPARE(rect->width(), 240.0);
QCOMPARE(rect->height(), 120.0);
+}
- delete loader;
+void tst_QQuickLoader::transientWindow() // QTBUG-52944
+{
+ QQuickView view;
+ view.setSource(testFileUrl("itemLoaderWindow.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
+ QVERIFY(root);
+ QQuickLoader *loader = root->findChild<QQuickLoader *>();
+ QVERIFY(loader);
+ QTRY_COMPARE(loader->status(), QQuickLoader::Ready);
+ QQuickWindowQmlImpl *loadedWindow = qobject_cast<QQuickWindowQmlImpl *>(loader->item());
+ QVERIFY(loadedWindow);
+ QCOMPARE(loadedWindow->visibility(), QWindow::Hidden);
+
+ QElapsedTimer timer;
+ qint64 viewVisibleTime = -1;
+ qint64 loadedWindowVisibleTime = -1;
+ connect(&view, &QWindow::visibleChanged,
+ [&viewVisibleTime, &timer]() { viewVisibleTime = timer.elapsed(); } );
+ connect(loadedWindow, &QQuickWindowQmlImpl::visibilityChanged,
+ [&loadedWindowVisibleTime, &timer]() { loadedWindowVisibleTime = timer.elapsed(); } );
+ timer.start();
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QTRY_VERIFY(loadedWindowVisibleTime >= 0);
+ QVERIFY(viewVisibleTime >= 0);
+
+ // now that we're sure they are both visible, which one became visible first?
+ qCDebug(lcTests) << "transient Window became visible" << (loadedWindowVisibleTime - viewVisibleTime) << "ms after the root Item";
+ QVERIFY((loadedWindowVisibleTime - viewVisibleTime) >= 0);
+
+ QWindowList windows = QGuiApplication::topLevelWindows();
+ QTRY_COMPARE(windows.size(), 2);
+
+ // TODO Ideally we would now close the outer window and make sure the transient window closes too.
+ // It works during manual testing because of QWindowPrivate::maybeQuitOnLastWindowClosed()
+ // but quitting an autotest doesn't make sense.
+}
+
+void tst_QQuickLoader::nestedTransientWindow() // QTBUG-52944
+{
+ QQuickView view;
+ view.setSource(testFileUrl("itemLoaderItemWindow.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
+ QVERIFY(root);
+ QQuickLoader *loader = root->findChild<QQuickLoader *>();
+ QVERIFY(loader);
+ QTRY_COMPARE(loader->status(), QQuickLoader::Ready);
+ QQuickItem *loadedItem = qobject_cast<QQuickItem *>(loader->item());
+ QVERIFY(loadedItem);
+ QQuickWindowQmlImpl *loadedWindow = loadedItem->findChild<QQuickWindowQmlImpl *>();
+ QVERIFY(loadedWindow);
+ QCOMPARE(loadedWindow->visibility(), QWindow::Hidden);
+
+ QElapsedTimer timer;
+ qint64 viewVisibleTime = -1;
+ qint64 loadedWindowVisibleTime = -1;
+ connect(&view, &QWindow::visibleChanged,
+ [&viewVisibleTime, &timer]() { viewVisibleTime = timer.elapsed(); } );
+ connect(loadedWindow, &QQuickWindowQmlImpl::visibilityChanged,
+ [&loadedWindowVisibleTime, &timer]() { loadedWindowVisibleTime = timer.elapsed(); } );
+ timer.start();
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QTRY_VERIFY(loadedWindowVisibleTime >= 0);
+ QVERIFY(viewVisibleTime >= 0);
+
+ // now that we're sure they are both visible, which one became visible first?
+ qCDebug(lcTests) << "transient Window became visible" << (loadedWindowVisibleTime - viewVisibleTime) << "ms after the root Item";
+ QVERIFY((loadedWindowVisibleTime - viewVisibleTime) >= 0);
+
+ QWindowList windows = QGuiApplication::topLevelWindows();
+ QTRY_COMPARE(windows.size(), 2);
+
+ // TODO Ideally we would now close the outer window and make sure the transient window closes too.
+ // It works during manual testing because of QWindowPrivate::maybeQuitOnLastWindowClosed()
+ // but quitting an autotest doesn't make sense.
}
void tst_QQuickLoader::sourceComponentGarbageCollection()
{
+ QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("sourceComponentGarbageCollection.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QMetaObject::invokeMethod(obj.data(), "setSourceComponent");
engine.collectGarbage();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QSignalSpy spy(obj.data(), SIGNAL(loaded()));
@@ -1220,6 +1271,176 @@ void tst_QQuickLoader::sourceComponentGarbageCollection()
QCOMPARE(spy.count(), 1);
}
+// QTBUG-51995
+void tst_QQuickLoader::bindings()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("bindings.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QQuickItem *game = object->property("game").value<QQuickItem*>();
+ QVERIFY(game);
+
+ QQuickLoader *loader = object->property("loader").value<QQuickLoader*>();
+ QVERIFY(loader);
+
+ QSignalSpy warningsSpy(&engine, SIGNAL(warnings(QList<QQmlError>)));
+
+ // Causes the Loader to become active
+ game->setState(QLatin1String("running"));
+ QTRY_VERIFY(loader->item());
+
+ // Causes the Loader to become inactive - should not cause binding errors
+ game->setState(QLatin1String("invalid"));
+ QTRY_VERIFY(!loader->item());
+
+ QString failureMessage;
+ if (!warningsSpy.isEmpty()) {
+ QDebug stream(&failureMessage);
+ stream << warningsSpy.first().first().value<QList<QQmlError>>();
+ }
+ QVERIFY2(warningsSpy.isEmpty(), qPrintable(failureMessage));
+}
+
+// QTBUG-47321
+void tst_QQuickLoader::parentErrors()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("parentErrors.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QQuickLoader *loader = object->property("loader").value<QQuickLoader*>();
+ QVERIFY(loader);
+
+ QSignalSpy warningsSpy(&engine, SIGNAL(warnings(QList<QQmlError>)));
+
+ // Give the loader a component
+ loader->setSourceComponent(object->property("component").value<QQmlComponent*>());
+ QTRY_VERIFY(loader->item());
+
+ // Clear the loader's component; should not cause binding errors
+ loader->setSourceComponent(nullptr);
+ QTRY_VERIFY(!loader->item());
+
+ QString failureMessage;
+ if (!warningsSpy.isEmpty()) {
+ QDebug stream(&failureMessage);
+ stream << warningsSpy.first().first().value<QList<QQmlError>>();
+ }
+ QVERIFY2(warningsSpy.isEmpty(), qPrintable(failureMessage));
+}
+
+class ObjectInRootContext: public QObject
+{
+ Q_OBJECT
+
+public:
+ int didIt = 0;
+
+public slots:
+ void doIt() {
+ didIt += 1;
+ }
+};
+
+void tst_QQuickLoader::rootContext()
+{
+ QQmlEngine engine;
+ ObjectInRootContext objectInRootContext;
+ engine.rootContext()->setContextProperty("objectInRootContext", &objectInRootContext);
+
+ QQmlComponent component(&engine, testFileUrl("rootContext.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QQuickLoader *loader = object->property("loader").value<QQuickLoader*>();
+ QVERIFY(loader);
+
+ QSignalSpy warningsSpy(&engine, SIGNAL(warnings(QList<QQmlError>)));
+
+ // Give the loader a component
+ loader->setSourceComponent(object->property("component").value<QQmlComponent*>());
+ QTRY_VERIFY(loader->active());
+ QTRY_VERIFY(loader->item());
+
+ QString failureMessage;
+ if (!warningsSpy.isEmpty()) {
+ QDebug stream(&failureMessage);
+ stream << warningsSpy.first().first().value<QList<QQmlError>>();
+ }
+ QVERIFY2(warningsSpy.isEmpty(), qPrintable(failureMessage));
+ QCOMPARE(objectInRootContext.didIt, 0);
+
+ // Deactivate the loader, which deletes the item.
+ // Check that a) there are no errors, and b) the objectInRootContext can still be resolved even
+ // after deactivating the loader. If it cannot, a ReferenceError for objectInRootContext is
+ // generated (and the 'doIt' counter in objectInRootContext will be 1 for the call before
+ // the deactivation).
+ loader->item()->setProperty("trigger", true);
+ QTRY_VERIFY(!loader->active());
+ QTRY_VERIFY(!loader->item());
+
+ if (!warningsSpy.isEmpty()) {
+ QDebug stream(&failureMessage);
+ stream << warningsSpy.first().first().value<QList<QQmlError>>();
+ }
+ QVERIFY2(warningsSpy.isEmpty(), qPrintable(failureMessage));
+ QCOMPARE(objectInRootContext.didIt, 2);
+}
+
+void tst_QQuickLoader::sourceURLKeepComponent()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(QByteArray(
+ "import QtQuick 2.0\n"
+ " Loader { id: loader\n }"),
+ dataDirectoryUrl());
+
+ QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create()));
+ loader->setSource(testFileUrl("/Rect120x60.qml"));
+
+ QVERIFY(loader);
+ QVERIFY(loader->item());
+ QVERIFY(loader->sourceComponent());
+ QCOMPARE(loader->progress(), 1.0);
+
+ const QPointer<QQmlComponent> sourceComponent = loader->sourceComponent();
+
+ //Ensure toggling active status does not recreate component
+ loader->setActive(false);
+ QVERIFY(!loader->item());
+ QVERIFY(loader->sourceComponent());
+ QCOMPARE(sourceComponent.data(), loader->sourceComponent());
+
+ loader->setActive(true);
+ QVERIFY(loader->item());
+ QVERIFY(loader->sourceComponent());
+ QCOMPARE(sourceComponent.data(), loader->sourceComponent());
+
+ loader->setActive(false);
+ QVERIFY(!loader->item());
+ QVERIFY(loader->sourceComponent());
+ QCOMPARE(sourceComponent.data(), loader->sourceComponent());
+
+ //Ensure changing source url causes component to be recreated when inactive
+ loader->setSource(testFileUrl("/BlueRect.qml"));
+
+ loader->setActive(true);
+ QVERIFY(loader->item());
+ QVERIFY(loader->sourceComponent());
+
+ const QPointer<QQmlComponent> newSourceComponent = loader->sourceComponent();
+ QVERIFY(sourceComponent.data() != newSourceComponent.data());
+
+ //Ensure changing source url causes component to be recreated when active
+ loader->setSource(testFileUrl("/Rect120x60.qml"));
+ QVERIFY(loader->sourceComponent() != newSourceComponent.data());
+
+}
+
QTEST_MAIN(tst_QQuickLoader)
#include "tst_qquickloader.moc"
diff --git a/tests/auto/quick/qquickmousearea/data/mask.qml b/tests/auto/quick/qquickmousearea/data/mask.qml
new file mode 100644
index 0000000000..ec315c2a63
--- /dev/null
+++ b/tests/auto/quick/qquickmousearea/data/mask.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.11
+import Test 1.0
+
+Item {
+ id: root
+ property int clicked: 0
+ property int pressed: 0
+ property int released: 0
+
+ width: 200; height: 200
+
+ MouseArea {
+ id: mouseArea
+ width: 200; height: 200
+ onPressed: { root.pressed++ }
+ onClicked: { root.clicked++ }
+ onReleased: { root.released++ }
+
+ containmentMask: CircleMask {
+ radius: mouseArea.width/2
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquickmousearea/data/nestedSendEvent.qml b/tests/auto/quick/qquickmousearea/data/nestedSendEvent.qml
new file mode 100644
index 0000000000..908a43b04e
--- /dev/null
+++ b/tests/auto/quick/qquickmousearea/data/nestedSendEvent.qml
@@ -0,0 +1,49 @@
+import QtQuick 2.11
+import QtQuick.Window 2.11
+import Test 1.0
+
+Window {
+ id: window
+ visible: true
+ width: 200
+ height: 200
+
+ property EventSender sender: EventSender { }
+
+ Item {
+ width: 200
+ height: 200
+
+ MouseArea {
+ anchors.fill: parent
+ }
+
+ Item {
+ width: 200
+ height: 200
+
+ Rectangle {
+ width: 200
+ height: 100
+ color: "red"
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: sender.sendMouseClick(window, 50, 50)
+ }
+ }
+
+ Rectangle {
+ y: 100
+ width: 200
+ height: 100
+ color: "yellow"
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: sender.sendMouseClick(window, 50, 50)
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickmousearea/data/twoMouseAreas.qml b/tests/auto/quick/qquickmousearea/data/twoMouseAreas.qml
new file mode 100644
index 0000000000..28f48c742a
--- /dev/null
+++ b/tests/auto/quick/qquickmousearea/data/twoMouseAreas.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.0
+import QtQuick.Window 2.0
+
+Rectangle {
+ width: 400
+ height: 300
+
+ property bool topPressed: top.pressed
+ property bool bottomPressed: bottom.pressed
+
+ MouseArea {
+ id: top
+ objectName: "top"
+ width: parent.width
+ height: parent.height / 2 - 2
+ Rectangle {
+ anchors.fill: parent
+ color: parent.pressed ? "MediumSeaGreen" : "beige"
+ }
+ }
+
+ MouseArea {
+ id: bottom
+ objectName: "bottom"
+ y: parent.height / 2
+ width: parent.width
+ height: parent.height / 2
+ Rectangle {
+ anchors.fill: parent
+ color: parent.pressed ? "MediumSeaGreen" : "beige"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickmousearea/qquickmousearea.pro b/tests/auto/quick/qquickmousearea/qquickmousearea.pro
index 3a4dfa946f..ee9d6dce2b 100644
--- a/tests/auto/quick/qquickmousearea/qquickmousearea.pro
+++ b/tests/auto/quick/qquickmousearea/qquickmousearea.pro
@@ -6,6 +6,8 @@ HEADERS += ../../shared/testhttpserver.h
SOURCES += tst_qquickmousearea.cpp \
../../shared/testhttpserver.cpp
+OTHER_FILES += $$files(data/*.qml)
+
include (../../shared/util.pri)
include (../shared/util.pri)
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 01bce46ccb..52d1458a53 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -43,30 +43,51 @@
#include <QtGui/QScreen>
#include <qpa/qwindowsysteminterface.h>
-// Initialize view, set Url, center in available geometry, move mouse away if desired
-static bool initView(QQuickView &v, const QUrl &url, bool moveMouseOut, QByteArray *errorMessage)
+class CircleMask : public QObject
{
- v.setBaseSize(QSize(240,320));
- v.setSource(url);
- while (v.status() == QQuickView::Loading)
- QTest::qWait(10);
- if (v.status() != QQuickView::Ready) {
- foreach (const QQmlError &e, v.errors())
- errorMessage->append(e.toString().toLocal8Bit() + '\n');
- return false;
+ Q_OBJECT
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
+
+public:
+ virtual ~CircleMask() {}
+ qreal radius() const { return m_radius; }
+ void setRadius(qreal radius)
+ {
+ if (m_radius == radius)
+ return;
+ m_radius = radius;
+ emit radiusChanged();
}
- const QRect screenGeometry = v.screen()->availableGeometry();
- const QSize size = v.size();
- const QPoint offset = QPoint(size.width() / 2, size.height() / 2);
- v.setFramePosition(screenGeometry.center() - offset);
-#if QT_CONFIG(cursor) // Get the cursor out of the way.
- if (moveMouseOut)
- QCursor::setPos(v.geometry().topRight() + QPoint(100, 100));
-#else
- Q_UNUSED(moveMouseOut)
-#endif
- return true;
-}
+
+ Q_INVOKABLE bool contains(const QPointF &point) const
+ {
+ QPointF center(m_radius, m_radius);
+ QLineF line(center, point);
+ return line.length() <= m_radius;
+ }
+
+signals:
+ void radiusChanged();
+
+private:
+ qreal m_radius;
+};
+
+class EventSender : public QObject {
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE void sendMouseClick(QObject* obj ,qreal x , qreal y) {
+ {
+ QMouseEvent event(QEvent::MouseButtonPress, QPointF(x , y), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ qApp->sendEvent(obj, &event);
+ }
+ {
+ QMouseEvent event(QEvent::MouseButtonRelease, QPointF(x , y), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ qApp->sendEvent(obj, &event);
+ }
+ }
+};
class tst_QQuickMouseArea: public QQmlDataTest
{
@@ -74,10 +95,13 @@ class tst_QQuickMouseArea: public QQmlDataTest
public:
tst_QQuickMouseArea()
: device(nullptr)
- {}
+ {
+ qmlRegisterType<CircleMask>("Test", 1, 0, "CircleMask");
+ qmlRegisterType<EventSender>("Test", 1, 0, "EventSender");
+ }
private slots:
- void initTestCase() Q_DECL_OVERRIDE;
+ void initTestCase() override;
void dragProperties();
void resetDrag();
void dragging_data() { acceptedButton_data(); }
@@ -130,6 +154,10 @@ private slots:
void notPressedAfterStolenGrab();
void pressAndHold_data();
void pressAndHold();
+ void pressOneAndTapAnother_data();
+ void pressOneAndTapAnother();
+ void mask();
+ void nestedEventDelivery();
private:
int startDragDistance() const {
@@ -182,22 +210,22 @@ void tst_QQuickMouseArea::dragProperties()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("dragproperties.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("dragproperties.qml"), true, &errorMessage), errorMessage.constData());
window.show();
- QTest::qWaitForWindowExposed(&window);
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
+ QVERIFY(mouseRegion != nullptr);
+ QVERIFY(drag != nullptr);
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QQuickItem *rootItem = qobject_cast<QQuickItem*>(window.rootObject());
- QVERIFY(rootItem != 0);
+ QVERIFY(rootItem != nullptr);
QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
drag->setTarget(rootItem);
QCOMPARE(targetSpy.count(),1);
@@ -280,24 +308,24 @@ void tst_QQuickMouseArea::resetDrag()
QQuickView window;
QByteArray errorMessage;
window.rootContext()->setContextProperty("haveTarget", QVariant(true));
- QVERIFY2(initView(window, testFileUrl("dragreset.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("dragreset.qml"), true, &errorMessage), errorMessage.constData());
window.show();
- QTest::qWaitForWindowExposed(&window);
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
+ QVERIFY(mouseRegion != nullptr);
+ QVERIFY(drag != nullptr);
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QQuickItem *rootItem = qobject_cast<QQuickItem*>(window.rootObject());
- QVERIFY(rootItem != 0);
+ QVERIFY(rootItem != nullptr);
QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
- QVERIFY(drag->target() != 0);
+ QVERIFY(drag->target() != nullptr);
window.rootContext()->setContextProperty("haveTarget", QVariant(false));
QCOMPARE(targetSpy.count(),1);
QVERIFY(!drag->target());
@@ -310,28 +338,28 @@ void tst_QQuickMouseArea::dragging()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
+ QVERIFY(mouseRegion != nullptr);
+ QVERIFY(drag != nullptr);
mouseRegion->setAcceptedButtons(acceptedButtons);
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
QPoint p = QPoint(100,100);
- QTest::mousePress(&window, button, 0, p);
+ QTest::mousePress(&window, button, Qt::NoModifier, p);
QVERIFY(!drag->active());
QCOMPARE(blackRect->x(), 50.0);
@@ -365,7 +393,7 @@ void tst_QQuickMouseArea::dragging()
QTRY_COMPARE(blackRect->x(), 61.0);
QCOMPARE(blackRect->y(), 61.0);
- QTest::mouseRelease(&window, button, 0, p);
+ QTest::mouseRelease(&window, button, Qt::NoModifier, p);
QTRY_VERIFY(!drag->active());
QTRY_COMPARE(blackRect->x(), 61.0);
QCOMPARE(blackRect->y(), 61.0);
@@ -375,11 +403,11 @@ void tst_QQuickMouseArea::dragSmoothed()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
QQuickDrag *drag = mouseRegion->drag();
@@ -387,17 +415,17 @@ void tst_QQuickMouseArea::dragSmoothed()
mouseRegion->setAcceptedButtons(Qt::LeftButton);
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QVERIFY(!drag->active());
QTest::mouseMove(&window, QPoint(100, 102), 50);
QTest::mouseMove(&window, QPoint(100, 106), 50);
QTest::mouseMove(&window, QPoint(100, 122), 50);
QTRY_COMPARE(blackRect->x(), 50.0);
QTRY_COMPARE(blackRect->y(), 66.0);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100,122));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,122));
// reset rect position
blackRect->setX(50.0);
@@ -406,14 +434,14 @@ void tst_QQuickMouseArea::dragSmoothed()
// now try with smoothed disabled
drag->setSmoothed(false);
QVERIFY(!drag->active());
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QVERIFY(!drag->active());
QTest::mouseMove(&window, QPoint(100, 102), 50);
QTest::mouseMove(&window, QPoint(100, 106), 50);
QTest::mouseMove(&window, QPoint(100, 122), 50);
QTRY_COMPARE(blackRect->x(), 50.0);
QTRY_COMPARE(blackRect->y(), 72.0);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100, 122));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 122));
}
void tst_QQuickMouseArea::dragThreshold_data()
@@ -429,11 +457,11 @@ void tst_QQuickMouseArea::dragThreshold()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
mouseRegion->setPreventStealing(preventStealing);
@@ -443,10 +471,10 @@ void tst_QQuickMouseArea::dragThreshold()
mouseRegion->setAcceptedButtons(Qt::LeftButton);
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QVERIFY(!drag->active());
QCOMPARE(blackRect->x(), 50.0);
QCOMPARE(blackRect->y(), 50.0);
@@ -465,18 +493,18 @@ void tst_QQuickMouseArea::dragThreshold()
QTRY_VERIFY(drag->active());
QTRY_COMPARE(blackRect->x(), 50.0);
QTRY_COMPARE(blackRect->y(), 66.0);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(122,122));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(122,122));
QTRY_VERIFY(!drag->active());
// Immediate drag threshold
drag->setThreshold(0);
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::mouseMove(&window, QPoint(100, 122), 50);
QVERIFY(!drag->active());
QTest::mouseMove(&window, QPoint(100, 123), 50);
QVERIFY(drag->active());
QTest::mouseMove(&window, QPoint(100, 124), 50);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100, 124));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 124));
QTRY_VERIFY(!drag->active());
drag->resetThreshold();
}
@@ -487,26 +515,26 @@ void tst_QQuickMouseArea::invalidDrag()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
window.show();
- QTest::qWaitForWindowExposed(&window);
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
+ QVERIFY(mouseRegion != nullptr);
+ QVERIFY(drag != nullptr);
mouseRegion->setAcceptedButtons(acceptedButtons);
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
- QTest::mousePress(&window, button, 0, QPoint(100,100));
+ QTest::mousePress(&window, button, Qt::NoModifier, QPoint(100,100));
QVERIFY(!drag->active());
QCOMPARE(blackRect->x(), 50.0);
@@ -524,7 +552,7 @@ void tst_QQuickMouseArea::invalidDrag()
QCOMPARE(blackRect->x(), 50.0);
QCOMPARE(blackRect->y(), 50.0);
- QTest::mouseRelease(&window, button, 0, QPoint(122,122));
+ QTest::mouseRelease(&window, button, Qt::NoModifier, QPoint(122,122));
QTest::qWait(50);
QVERIFY(!drag->active());
@@ -536,28 +564,28 @@ void tst_QQuickMouseArea::cancelDragging()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
+ QVERIFY(mouseRegion != nullptr);
+ QVERIFY(drag != nullptr);
mouseRegion->setAcceptedButtons(Qt::LeftButton);
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
QPoint p = QPoint(100,100);
- QTest::mousePress(&window, Qt::LeftButton, 0, p);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
QVERIFY(!drag->active());
QCOMPARE(blackRect->x(), 50.0);
@@ -583,7 +611,7 @@ void tst_QQuickMouseArea::cancelDragging()
QCOMPARE(blackRect->x(), 61.0);
QCOMPARE(blackRect->y(), 61.0);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(122,122));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(122,122));
}
// QTBUG-58347
@@ -591,7 +619,7 @@ void tst_QQuickMouseArea::availableDistanceLessThanDragThreshold()
{
QQuickView view;
QByteArray errorMessage;
- QVERIFY2(initView(view, testFileUrl("availableDistanceLessThanDragThreshold.qml"), true, &errorMessage),
+ QVERIFY2(QQuickTest::initView(view, testFileUrl("availableDistanceLessThanDragThreshold.qml"), true, &errorMessage),
errorMessage.constData());
view.show();
view.requestActivate();
@@ -602,14 +630,14 @@ void tst_QQuickMouseArea::availableDistanceLessThanDragThreshold()
QVERIFY(mouseArea);
QPoint position(100, 100);
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
QTest::qWait(10);
position.setX(301);
QTest::mouseMove(&view, position);
position.setX(501);
QTest::mouseMove(&view, position);
QVERIFY(mouseArea->drag()->active());
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
QVERIFY(!mouseArea->drag()->active());
QCOMPARE(mouseArea->x(), 200.0);
@@ -619,10 +647,10 @@ void tst_QQuickMouseArea::setDragOnPressed()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("setDragOnPressed.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("setDragOnPressed.qml"), true, &errorMessage), errorMessage.constData());
window.show();
- QTest::qWaitForWindowExposed(&window);
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseArea = qobject_cast<QQuickMouseArea *>(window.rootObject());
QVERIFY(mouseArea);
@@ -632,7 +660,7 @@ void tst_QQuickMouseArea::setDragOnPressed()
QVERIFY(target);
QPoint p = QPoint(100, 100);
- QTest::mousePress(&window, Qt::LeftButton, 0, p);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
QQuickDrag *drag = mouseArea->drag();
QVERIFY(drag);
@@ -653,7 +681,7 @@ void tst_QQuickMouseArea::setDragOnPressed()
QTRY_COMPARE(target->x(), 61.0);
QCOMPARE(target->y(), 50.0);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, p);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p);
QTRY_VERIFY(!drag->active());
QCOMPARE(target->x(), 61.0);
QCOMPARE(target->y(), 50.0);
@@ -663,21 +691,21 @@ void tst_QQuickMouseArea::updateMouseAreaPosOnClick()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("updateMousePosOnClick.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("updateMousePosOnClick.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
- QVERIFY(mouseRegion != 0);
+ QVERIFY(mouseRegion != nullptr);
QQuickRectangle *rect = window.rootObject()->findChild<QQuickRectangle*>("ball");
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(mouseRegion->mouseX(), rect->x());
QCOMPARE(mouseRegion->mouseY(), rect->y());
- QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &event);
QCOMPARE(mouseRegion->mouseX(), 100.0);
@@ -691,21 +719,21 @@ void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("updateMousePosOnResize.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("updateMousePosOnResize.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
- QVERIFY(mouseRegion != 0);
+ QVERIFY(mouseRegion != nullptr);
QQuickRectangle *rect = window.rootObject()->findChild<QQuickRectangle*>("brother");
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(mouseRegion->mouseX(), 0.0);
QCOMPARE(mouseRegion->mouseY(), 0.0);
- QMouseEvent event(QEvent::MouseButtonPress, rect->position().toPoint(), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent event(QEvent::MouseButtonPress, rect->position().toPoint(), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &event);
QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
@@ -727,14 +755,14 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
// We handle onPressAndHold, therefore no onClicked
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("clickandhold.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("clickandhold.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseArea = qobject_cast<QQuickMouseArea*>(window.rootObject()->children().first());
QVERIFY(mouseArea);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
QCOMPARE(mouseArea->pressedButtons(), Qt::LeftButton);
@@ -748,7 +776,7 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
QVERIFY(!window.rootObject()->property("clicked").toBool());
QVERIFY(window.rootObject()->property("held").toBool());
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &releaseEvent);
QTRY_VERIFY(window.rootObject()->property("held").toBool());
@@ -759,19 +787,19 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
// We do not handle onPressAndHold, therefore we get onClicked
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("noclickandhold.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("noclickandhold.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
QVERIFY(!window.rootObject()->property("clicked").toBool());
QTest::qWait(1000);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &releaseEvent);
QVERIFY(window.rootObject()->property("clicked").toBool());
@@ -782,10 +810,10 @@ void tst_QQuickMouseArea::onMousePressRejected()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("rejectEvent.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("rejectEvent.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QVERIFY(window.rootObject()->property("enabled").toBool());
QVERIFY(!window.rootObject()->property("mr1_pressed").toBool());
@@ -795,7 +823,7 @@ void tst_QQuickMouseArea::onMousePressRejected()
QVERIFY(!window.rootObject()->property("mr2_released").toBool());
QVERIFY(!window.rootObject()->property("mr2_canceled").toBool());
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
QVERIFY(window.rootObject()->property("mr1_pressed").toBool());
@@ -807,7 +835,7 @@ void tst_QQuickMouseArea::onMousePressRejected()
QTest::qWait(200);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &releaseEvent);
QVERIFY(window.rootObject()->property("mr1_released").toBool());
@@ -829,10 +857,10 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("pressedCanceled.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("pressedCanceled.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QVERIFY(!window.rootObject()->property("pressed").toBool());
QVERIFY(!window.rootObject()->property("canceled").toBool());
@@ -842,8 +870,8 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QCOMPARE(window.rootObject()->property("clicked").toInt(), expectedClicks);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
@@ -860,7 +888,7 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QCOMPARE(window.rootObject()->property("clicked").toInt(), ++expectedClicks);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent2);
QTRY_VERIFY(window.rootObject()->property("pressed").toBool());
@@ -873,7 +901,7 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QWindow *secondWindow = qvariant_cast<QWindow*>(window.rootObject()->property("secondWindow"));
secondWindow->setProperty("visible", true);
- QTest::qWaitForWindowExposed(secondWindow);
+ QVERIFY(QTest::qWaitForWindowExposed(secondWindow));
QTRY_VERIFY(!window.rootObject()->property("pressed").toBool());
QVERIFY(window.rootObject()->property("canceled").toBool());
@@ -902,10 +930,10 @@ void tst_QQuickMouseArea::doubleClick()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("doubleclick.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("doubleclick.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea *>("mousearea");
QVERIFY(mouseArea);
@@ -913,16 +941,16 @@ void tst_QQuickMouseArea::doubleClick()
// The sequence for a double click is:
// press, release, (click), press, double click, release
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, 0);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, 0);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("released").toInt(), 1);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, 0);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -939,19 +967,19 @@ void tst_QQuickMouseArea::clickTwice()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("clicktwice.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("clicktwice.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea *>("mousearea");
QVERIFY(mouseArea);
mouseArea->setAcceptedButtons(acceptedButtons);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, 0);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, 0);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("pressed").toInt(), 1);
@@ -959,7 +987,7 @@ void tst_QQuickMouseArea::clickTwice()
QCOMPARE(window.rootObject()->property("clicked").toInt(), 1);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, 0);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -975,10 +1003,10 @@ void tst_QQuickMouseArea::invalidClick()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("doubleclick.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("doubleclick.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea *>("mousearea");
QVERIFY(mouseArea);
@@ -986,16 +1014,16 @@ void tst_QQuickMouseArea::invalidClick()
// The sequence for a double click is:
// press, release, (click), press, double click, release
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, 0);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, 0);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("released").toInt(), 0);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, 0);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -1008,19 +1036,19 @@ void tst_QQuickMouseArea::pressedOrdering()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("pressedOrdering.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("pressedOrdering.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("base"));
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &pressEvent);
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("pressed"));
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("toggled"));
@@ -1034,21 +1062,21 @@ void tst_QQuickMouseArea::preventStealing()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("preventstealing.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("preventstealing.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window.rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea*>("mousearea");
- QVERIFY(mouseArea != 0);
+ QVERIFY(mouseArea != nullptr);
QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
QPoint p = QPoint(80, 80);
- QTest::mousePress(&window, Qt::LeftButton, 0, p);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
// Without preventStealing, mouse movement over MouseArea would
// cause the Flickable to steal mouse and trigger content movement.
@@ -1071,13 +1099,13 @@ void tst_QQuickMouseArea::preventStealing()
QCOMPARE(flickable->contentX(), 0.);
QCOMPARE(flickable->contentY(), 0.);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, p);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p);
// Now allow stealing and confirm Flickable does its thing.
window.rootObject()->setProperty("stealing", false);
p = QPoint(80, 80);
- QTest::mousePress(&window, Qt::LeftButton, 0, p);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
// Without preventStealing, mouse movement over MouseArea would
// cause the Flickable to steal mouse and trigger content movement.
@@ -1100,7 +1128,7 @@ void tst_QQuickMouseArea::preventStealing()
QTRY_COMPARE(flickable->contentX(), 20.);
QCOMPARE(flickable->contentY(), 20.);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, p);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p);
}
void tst_QQuickMouseArea::clickThrough()
@@ -1108,30 +1136,30 @@ void tst_QQuickMouseArea::clickThrough()
//With no handlers defined click, doubleClick and PressAndHold should propagate to those with handlers
QScopedPointer<QQuickView> window(new QQuickView);
QByteArray errorMessage;
- QVERIFY2(initView(*window.data(), testFileUrl("clickThrough.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(*window.data(), testFileUrl("clickThrough.qml"), true, &errorMessage), errorMessage.constData());
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
// to avoid generating a double click.
const int doubleClickInterval = qApp->styleHints()->mouseDoubleClickInterval() + 10;
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100));
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTRY_COMPARE(window->rootObject()->property("presses").toInt(), 0);
QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 1);
QCOMPARE(window->rootObject()->property("doubleClicks").toInt(), 0);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100), doubleClickInterval);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100), doubleClickInterval);
QTest::qWait(1000);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTRY_COMPARE(window->rootObject()->property("presses").toInt(), 0);
QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 1);
QTRY_COMPARE(window->rootObject()->property("pressAndHolds").toInt(), 1);
- QTest::mouseDClick(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseDClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::qWait(100);
QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
@@ -1142,27 +1170,27 @@ void tst_QQuickMouseArea::clickThrough()
window.reset(new QQuickView);
//With handlers defined click, doubleClick and PressAndHold should propagate only when explicitly ignored
- QVERIFY2(initView(*window.data(), testFileUrl("clickThrough2.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(*window.data(), testFileUrl("clickThrough2.qml"), true, &errorMessage), errorMessage.constData());
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100));
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
QCOMPARE(window->rootObject()->property("clicks").toInt(), 0);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100), doubleClickInterval);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100), doubleClickInterval);
QTest::qWait(1000);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::qWait(100);
QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
QCOMPARE(window->rootObject()->property("clicks").toInt(), 0);
QCOMPARE(window->rootObject()->property("pressAndHolds").toInt(), 0);
- QTest::mouseDClick(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseDClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::qWait(100);
QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
@@ -1172,22 +1200,22 @@ void tst_QQuickMouseArea::clickThrough()
window->rootObject()->setProperty("letThrough", QVariant(true));
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100), doubleClickInterval);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100), doubleClickInterval);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 1);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100), doubleClickInterval);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100), doubleClickInterval);
QTest::qWait(1000);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::qWait(100);
QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
QCOMPARE(window->rootObject()->property("clicks").toInt(), 1);
QCOMPARE(window->rootObject()->property("pressAndHolds").toInt(), 1);
- QTest::mouseDClick(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseDClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::qWait(100);
QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
@@ -1197,15 +1225,15 @@ void tst_QQuickMouseArea::clickThrough()
window->rootObject()->setProperty("noPropagation", QVariant(true));
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100), doubleClickInterval);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100), doubleClickInterval);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100), doubleClickInterval);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100), doubleClickInterval);
QTest::qWait(1000);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::qWait(100);
- QTest::mouseDClick(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mouseDClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::qWait(100);
QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
@@ -1216,21 +1244,21 @@ void tst_QQuickMouseArea::clickThrough()
window.reset(new QQuickView);
//QTBUG-34368 - Shouldn't propagate to disabled mouse areas
- QVERIFY2(initView(*window.data(), testFileUrl("qtbug34368.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(*window.data(), testFileUrl("qtbug34368.qml"), true, &errorMessage), errorMessage.constData());
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100), doubleClickInterval);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100), doubleClickInterval);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QCOMPARE(window->rootObject()->property("clicksEnabled").toInt(), 1);
QCOMPARE(window->rootObject()->property("clicksDisabled").toInt(), 1); //Not disabled yet
window->rootObject()->setProperty("disableLower", QVariant(true));
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100), doubleClickInterval);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100), doubleClickInterval);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QCOMPARE(window->rootObject()->property("clicksEnabled").toInt(), 2);
QCOMPARE(window->rootObject()->property("clicksDisabled").toInt(), 1); //disabled, shouldn't increment
@@ -1238,24 +1266,24 @@ void tst_QQuickMouseArea::clickThrough()
window.reset(new QQuickView);
//QTBUG-49100
- QVERIFY2(initView(*window.data(), testFileUrl("qtbug49100.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(*window.data(), testFileUrl("qtbug49100.qml"), true, &errorMessage), errorMessage.constData());
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(100,100));
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
}
void tst_QQuickMouseArea::hoverPosition()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("hoverPosition.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("hoverPosition.qml"), true, &errorMessage), errorMessage.constData());
QQuickItem *root = window.rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QCOMPARE(root->property("mouseX").toReal(), qreal(0));
QCOMPARE(root->property("mouseY").toReal(), qreal(0));
@@ -1272,20 +1300,20 @@ void tst_QQuickMouseArea::hoverPropagation()
//QTBUG-18175, to behave like GV did.
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("hoverPropagation.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("hoverPropagation.qml"), true, &errorMessage), errorMessage.constData());
QQuickItem *root = window.rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QCOMPARE(root->property("point1").toBool(), false);
QCOMPARE(root->property("point2").toBool(), false);
- QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, 0);
+ QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, nullptr);
QGuiApplication::sendEvent(&window, &moveEvent);
QCOMPARE(root->property("point1").toBool(), true);
QCOMPARE(root->property("point2").toBool(), false);
- QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, 0);
+ QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, nullptr);
QGuiApplication::sendEvent(&window, &moveEvent2);
QCOMPARE(root->property("point1").toBool(), false);
QCOMPARE(root->property("point2").toBool(), true);
@@ -1293,14 +1321,18 @@ void tst_QQuickMouseArea::hoverPropagation()
void tst_QQuickMouseArea::hoverVisible()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("hoverVisible.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("hoverVisible.qml"), true, &errorMessage), errorMessage.constData());
QQuickItem *root = window.rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QQuickMouseArea *mouseTracker = window.rootObject()->findChild<QQuickMouseArea*>("mousetracker");
- QVERIFY(mouseTracker != 0);
+ QVERIFY(mouseTracker != nullptr);
QSignalSpy enteredSpy(mouseTracker, SIGNAL(entered()));
@@ -1323,12 +1355,12 @@ void tst_QQuickMouseArea::hoverAfterPress()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("hoverAfterPress.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("hoverAfterPress.qml"), true, &errorMessage), errorMessage.constData());
QQuickItem *root = window.rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea*>("mouseArea");
- QVERIFY(mouseArea != 0);
+ QVERIFY(mouseArea != nullptr);
QTest::mouseMove(&window, QPoint(22,33));
QCOMPARE(mouseArea->hovered(), false);
QTest::mouseMove(&window, QPoint(200,200));
@@ -1349,13 +1381,13 @@ void tst_QQuickMouseArea::subtreeHoverEnabled()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("qtbug54019.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("qtbug54019.qml"), true, &errorMessage), errorMessage.constData());
QQuickItem *root = window.rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QQuickMouseArea *mouseArea = root->findChild<QQuickMouseArea*>();
QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root);
- QVERIFY(mouseArea != 0);
+ QVERIFY(mouseArea != nullptr);
QTest::mouseMove(&window, QPoint(10, 160));
QCOMPARE(mouseArea->hovered(), false);
QVERIFY(rootPrivate->subtreeHoverEnabled);
@@ -1369,15 +1401,15 @@ void tst_QQuickMouseArea::disableAfterPress()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
QQuickDrag *drag = mouseArea->drag();
- QVERIFY(mouseArea != 0);
- QVERIFY(drag != 0);
+ QVERIFY(mouseArea != nullptr);
+ QVERIFY(drag != nullptr);
QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
QSignalSpy mousePressSpy(mouseArea, SIGNAL(pressed(QQuickMouseEvent*)));
@@ -1385,12 +1417,12 @@ void tst_QQuickMouseArea::disableAfterPress()
// target
QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
QPoint p = QPoint(100,100);
- QTest::mousePress(&window, Qt::LeftButton, 0, p);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
QTRY_COMPARE(mousePressSpy.count(), 1);
QVERIFY(!drag->active());
@@ -1428,7 +1460,7 @@ void tst_QQuickMouseArea::disableAfterPress()
QVERIFY(mouseArea->pressed());
QVERIFY(mouseArea->hovered());
- QTest::mouseRelease(&window, Qt::LeftButton, 0, p);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p);
QTRY_COMPARE(mouseReleaseSpy.count(), 1);
@@ -1447,7 +1479,7 @@ void tst_QQuickMouseArea::disableAfterPress()
mousePositionSpy.clear();
mouseReleaseSpy.clear();
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
QTest::qWait(50);
QCOMPARE(mousePressSpy.count(), 0);
@@ -1462,7 +1494,7 @@ void tst_QQuickMouseArea::disableAfterPress()
QCOMPARE(blackRect->x(), 50.0);
QCOMPARE(blackRect->y(), 50.0);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(122,122));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(122,122));
QTest::qWait(50);
QCOMPARE(mouseReleaseSpy.count(), 0);
@@ -1472,9 +1504,9 @@ void tst_QQuickMouseArea::onWheel()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("wheel.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("wheel.qml"), true, &errorMessage), errorMessage.constData());
QQuickItem *root = window.rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QWheelEvent wheelEvent(QPoint(10, 32), QPoint(10, 32), QPoint(60, 20), QPoint(0, 120),
0, Qt::Vertical,Qt::NoButton, Qt::ControlModifier);
@@ -1516,13 +1548,13 @@ void tst_QQuickMouseArea::transformedMouseArea()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("transformedMouseArea.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("transformedMouseArea.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea *>("mouseArea");
- QVERIFY(mouseArea != 0);
+ QVERIFY(mouseArea != nullptr);
foreach (const QPoint &point, points) {
// check hover
@@ -1530,133 +1562,123 @@ void tst_QQuickMouseArea::transformedMouseArea()
QTRY_COMPARE(mouseArea->property("containsMouse").toBool(), insideTarget);
// check mouse press
- QTest::mousePress(&window, Qt::LeftButton, 0, point);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, point);
QTRY_COMPARE(mouseArea->property("pressed").toBool(), insideTarget);
// check mouse release
- QTest::mouseRelease(&window, Qt::LeftButton, 0, point);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, point);
QTRY_COMPARE(mouseArea->property("pressed").toBool(), false);
}
}
+struct MouseEvent {
+ QEvent::Type type;
+ Qt::MouseButton button;
+};
+Q_DECLARE_METATYPE(MouseEvent)
+
void tst_QQuickMouseArea::pressedMultipleButtons_data()
{
QTest::addColumn<Qt::MouseButtons>("accepted");
- QTest::addColumn<QList<Qt::MouseButtons> >("buttons");
+ QTest::addColumn<QList<MouseEvent> >("mouseEvents");
QTest::addColumn<QList<bool> >("pressed");
QTest::addColumn<QList<Qt::MouseButtons> >("pressedButtons");
QTest::addColumn<int>("changeCount");
- QList<Qt::MouseButtons> buttons;
+ Qt::MouseButtons accepted;
+ QList<MouseEvent> mouseEvents;
QList<bool> pressed;
QList<Qt::MouseButtons> pressedButtons;
- buttons << Qt::LeftButton
- << (Qt::LeftButton | Qt::RightButton)
- << Qt::LeftButton
- << 0;
- pressed << true
- << true
- << true
- << false;
- pressedButtons << Qt::LeftButton
- << Qt::LeftButton
- << Qt::LeftButton
- << 0;
- QTest::newRow("Accept Left - Press left, Press Right, Release Right")
- << Qt::MouseButtons(Qt::LeftButton) << buttons << pressed << pressedButtons << 2;
-
- buttons.clear();
- pressed.clear();
- pressedButtons.clear();
- buttons << Qt::LeftButton
- << (Qt::LeftButton | Qt::RightButton)
- << Qt::RightButton
- << 0;
- pressed << true
- << true
- << false
- << false;
- pressedButtons << Qt::LeftButton
- << Qt::LeftButton
- << 0
- << 0;
- QTest::newRow("Accept Left - Press left, Press Right, Release Left")
- << Qt::MouseButtons(Qt::LeftButton) << buttons << pressed << pressedButtons << 2;
-
- buttons.clear();
- pressed.clear();
- pressedButtons.clear();
- buttons << Qt::LeftButton
- << (Qt::LeftButton | Qt::RightButton)
- << Qt::LeftButton
- << 0;
- pressed << true
- << true
- << true
- << false;
- pressedButtons << Qt::LeftButton
- << (Qt::LeftButton | Qt::RightButton)
- << Qt::LeftButton
- << 0;
- QTest::newRow("Accept Left|Right - Press left, Press Right, Release Right")
- << (Qt::LeftButton | Qt::RightButton) << buttons << pressed << pressedButtons << 4;
-
- buttons.clear();
- pressed.clear();
- pressedButtons.clear();
- buttons << Qt::RightButton
- << (Qt::LeftButton | Qt::RightButton)
- << Qt::LeftButton
- << 0;
- pressed << true
- << true
- << false
- << false;
- pressedButtons << Qt::RightButton
- << Qt::RightButton
- << 0
- << 0;
- QTest::newRow("Accept Right - Press Right, Press Left, Release Right")
- << Qt::MouseButtons(Qt::RightButton) << buttons << pressed << pressedButtons << 2;
+ int changeCount;
+
+ MouseEvent leftPress = { QEvent::MouseButtonPress, Qt::LeftButton };
+ MouseEvent leftRelease = { QEvent::MouseButtonRelease, Qt::LeftButton };
+ MouseEvent rightPress = { QEvent::MouseButtonPress, Qt::RightButton };
+ MouseEvent rightRelease = { QEvent::MouseButtonRelease, Qt::RightButton };
+
+ auto addRowWithFormattedTitleAndReset = [&]() {
+ QByteArray title;
+ title.append("Accept:");
+ if (accepted & Qt::LeftButton)
+ title.append(" LeftButton");
+ if (accepted & Qt::RightButton)
+ title.append(" RightButton");
+ title.append(" | Events:");
+ for (MouseEvent event : mouseEvents) {
+ title.append(event.type == QEvent::MouseButtonPress ? " Press" : " Release");
+ title.append(event.button == Qt::LeftButton ? " Left," : " Right,");
+ }
+ title.chop(1); // remove last comma
+ QTest::newRow(title) << accepted << mouseEvents << pressed << pressedButtons << changeCount;
+
+ mouseEvents.clear();
+ pressed.clear();
+ pressedButtons.clear();
+ };
+
+ accepted = Qt::LeftButton;
+ changeCount = 2;
+ mouseEvents << leftPress << rightPress << rightRelease << leftRelease;
+ pressed << true << true << true << false;
+ pressedButtons << Qt::LeftButton << Qt::LeftButton << Qt::LeftButton << Qt::NoButton;
+ addRowWithFormattedTitleAndReset();
+
+ accepted = Qt::LeftButton;
+ changeCount = 2;
+ mouseEvents << leftPress << rightPress << leftRelease << rightRelease;
+ pressed << true << true << false << false;
+ pressedButtons << Qt::LeftButton << Qt::LeftButton << Qt::NoButton << Qt::NoButton;
+ addRowWithFormattedTitleAndReset();
+
+ accepted = Qt::LeftButton | Qt::RightButton;
+ changeCount = 4;
+ mouseEvents << leftPress << rightPress << rightRelease << leftRelease;
+ pressed << true << true << true << false;
+ pressedButtons << Qt::LeftButton << (Qt::LeftButton | Qt::RightButton) << Qt::LeftButton
+ << Qt::NoButton;
+ addRowWithFormattedTitleAndReset();
+
+ accepted = Qt::RightButton;
+ changeCount = 2;
+ mouseEvents << rightPress << leftPress << rightRelease << leftRelease;
+ pressed << true << true << false << false;
+ pressedButtons << Qt::RightButton << Qt::RightButton << Qt::NoButton << Qt::NoButton;
+ addRowWithFormattedTitleAndReset();
}
void tst_QQuickMouseArea::pressedMultipleButtons()
{
QFETCH(Qt::MouseButtons, accepted);
- QFETCH(QList<Qt::MouseButtons>, buttons);
+ QFETCH(QList<MouseEvent>, mouseEvents);
QFETCH(QList<bool>, pressed);
QFETCH(QList<Qt::MouseButtons>, pressedButtons);
QFETCH(int, changeCount);
QQuickView view;
QByteArray errorMessage;
- QVERIFY2(initView(view, testFileUrl("simple.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(view, testFileUrl("simple.qml"), true, &errorMessage), errorMessage.constData());
view.show();
- QTest::qWaitForWindowExposed(&view);
- QVERIFY(view.rootObject() != 0);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QVERIFY(view.rootObject() != nullptr);
QQuickMouseArea *mouseArea = view.rootObject()->findChild<QQuickMouseArea *>("mousearea");
- QVERIFY(mouseArea != 0);
+ QVERIFY(mouseArea != nullptr);
QSignalSpy pressedSpy(mouseArea, SIGNAL(pressedChanged()));
QSignalSpy pressedButtonsSpy(mouseArea, SIGNAL(pressedButtonsChanged()));
mouseArea->setAcceptedMouseButtons(accepted);
- QPoint point(10,10);
-
- for (int i = 0; i < buttons.count(); ++i) {
- int btns = buttons.at(i);
-
- // The windowsysteminterface takes care of sending releases
- QTest::mousePress(&view, (Qt::MouseButton)btns, 0, point);
-
+ QPoint point(10, 10);
+ for (int i = 0; i < mouseEvents.count(); ++i) {
+ const MouseEvent mouseEvent = mouseEvents.at(i);
+ if (mouseEvent.type == QEvent::MouseButtonPress)
+ QTest::mousePress(&view, mouseEvent.button, Qt::NoModifier, point);
+ else
+ QTest::mouseRelease(&view, mouseEvent.button, Qt::NoModifier, point);
QCOMPARE(mouseArea->pressed(), pressed.at(i));
QCOMPARE(mouseArea->pressedButtons(), pressedButtons.at(i));
}
- QTest::mousePress(&view, Qt::NoButton, 0, point);
- QCOMPARE(mouseArea->pressed(), false);
-
QCOMPARE(pressedSpy.count(), 2);
QCOMPARE(pressedButtonsSpy.count(), changeCount);
}
@@ -1665,28 +1687,28 @@ void tst_QQuickMouseArea::changeAxis()
{
QQuickView view;
QByteArray errorMessage;
- QVERIFY2(initView(view, testFileUrl("changeAxis.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(view, testFileUrl("changeAxis.qml"), true, &errorMessage), errorMessage.constData());
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
- QTRY_VERIFY(view.rootObject() != 0);
+ QTRY_VERIFY(view.rootObject() != nullptr);
QQuickMouseArea *mouseRegion = view.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
QQuickDrag *drag = mouseRegion->drag();
- QVERIFY(mouseRegion != 0);
- QVERIFY(drag != 0);
+ QVERIFY(mouseRegion != nullptr);
+ QVERIFY(drag != nullptr);
mouseRegion->setAcceptedButtons(Qt::LeftButton);
// target
QQuickItem *blackRect = view.rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, drag->target());
QVERIFY(!drag->active());
// Start a diagonal drag
QPoint p = QPoint(100, 100);
- QTest::mousePress(&view, Qt::LeftButton, 0, p);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, p);
QVERIFY(!drag->active());
QCOMPARE(blackRect->x(), 50.0);
@@ -1717,7 +1739,7 @@ void tst_QQuickMouseArea::changeAxis()
QTRY_COMPARE(blackRect->y(), 94.0);
QCOMPARE(blackRect->x(), 83.0);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, p);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, p);
QTRY_VERIFY(!drag->active());
QCOMPARE(blackRect->x(), 83.0);
@@ -1758,14 +1780,14 @@ void tst_QQuickMouseArea::moveAndReleaseWithoutPress()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("moveAndReleaseWithoutPress.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("moveAndReleaseWithoutPress.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QObject *root = window.rootObject();
QVERIFY(root);
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
// the press was not accepted, make sure there is no move or release event
QTest::mouseMove(&window, QPoint(110,110), 50);
@@ -1775,7 +1797,7 @@ void tst_QQuickMouseArea::moveAndReleaseWithoutPress()
QTest::qWait(100);
QCOMPARE(root->property("hadMove").toBool(), false);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(110,110));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(110,110));
QTest::qWait(100);
QCOMPARE(root->property("hadRelease").toBool(), false);
}
@@ -1798,7 +1820,7 @@ void tst_QQuickMouseArea::nestedStopAtBounds()
QQuickView view;
QByteArray errorMessage;
- QVERIFY2(initView(view, testFileUrl("nestedStopAtBounds.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(view, testFileUrl("nestedStopAtBounds.qml"), true, &errorMessage), errorMessage.constData());
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(&view));
@@ -1819,7 +1841,7 @@ void tst_QQuickMouseArea::nestedStopAtBounds()
int &axis = transpose ? position.ry() : position.rx();
// drag toward the aligned boundary. Outer mouse area dragged.
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
QTest::qWait(10);
axis += invert ? threshold * 2 : -threshold * 2;
QTest::mouseMove(&view, position);
@@ -1827,7 +1849,7 @@ void tst_QQuickMouseArea::nestedStopAtBounds()
QTest::mouseMove(&view, position);
QCOMPARE(outer->drag()->active(), true);
QCOMPARE(inner->drag()->active(), false);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
QVERIFY(!outer->drag()->active());
@@ -1836,7 +1858,7 @@ void tst_QQuickMouseArea::nestedStopAtBounds()
outer->setY(50);
// drag away from the aligned boundary. Inner mouse area dragged.
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
QTest::qWait(10);
axis += invert ? -threshold * 2 : threshold * 2;
QTest::mouseMove(&view, position);
@@ -1844,14 +1866,14 @@ void tst_QQuickMouseArea::nestedStopAtBounds()
QTest::mouseMove(&view, position);
QTRY_COMPARE(outer->drag()->active(), false);
QTRY_COMPARE(inner->drag()->active(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
}
void tst_QQuickMouseArea::nestedFlickableStopAtBounds()
{
QQuickView view;
QByteArray errorMessage;
- QVERIFY2(initView(view, testFileUrl("nestedFlickableStopAtBounds.qml"), false, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(view, testFileUrl("nestedFlickableStopAtBounds.qml"), false, &errorMessage), errorMessage.constData());
view.show();
view.requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(&view));
@@ -1869,7 +1891,7 @@ void tst_QQuickMouseArea::nestedFlickableStopAtBounds()
int &pos = position.ry();
// Drag up - should move the Flickable to end
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
QTest::qWait(10);
pos -= threshold * 2;
QTest::mouseMove(&view, position);
@@ -1881,7 +1903,7 @@ void tst_QQuickMouseArea::nestedFlickableStopAtBounds()
QVERIFY(flickable->isDragging());
QVERIFY(!mouseArea->drag()->active());
QCOMPARE(flickable->isAtYEnd(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
QTRY_VERIFY(!flickable->isMoving());
@@ -1889,7 +1911,7 @@ void tst_QQuickMouseArea::nestedFlickableStopAtBounds()
// Drag up again - should activate MouseArea drag
QVERIFY(!mouseArea->drag()->active());
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
QTest::qWait(10);
pos -= threshold * 2;
QTest::mouseMove(&view, position);
@@ -1901,12 +1923,12 @@ void tst_QQuickMouseArea::nestedFlickableStopAtBounds()
QVERIFY(mouseArea->drag()->active());
QCOMPARE(flickable->isAtYEnd(), true);
QVERIFY(!flickable->isDragging());
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
// Drag to the top and verify that the MouseArea doesn't steal the grab when we drag back (QTBUG-56036)
pos = 50;
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
QTest::qWait(10);
pos += threshold;
QTest::mouseMove(&view, position);
@@ -1918,14 +1940,14 @@ void tst_QQuickMouseArea::nestedFlickableStopAtBounds()
QVERIFY(flickable->isDragging());
QVERIFY(!mouseArea->drag()->active());
QCOMPARE(flickable->isAtYBeginning(), true);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
QTRY_VERIFY(!flickable->isMoving());
pos = 280;
// Drag up again - should not activate MouseArea drag
- QTest::mousePress(&view, Qt::LeftButton, 0, position);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
QTest::qWait(10);
pos -= threshold;
QTest::mouseMove(&view, position);
@@ -1936,7 +1958,7 @@ void tst_QQuickMouseArea::nestedFlickableStopAtBounds()
QTest::mouseMove(&view, position);
QVERIFY(flickable->isDragging());
QVERIFY(!mouseArea->drag()->active());
- QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
}
void tst_QQuickMouseArea::containsPress_data()
@@ -1953,15 +1975,15 @@ void tst_QQuickMouseArea::containsPress()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("containsPress.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("containsPress.qml"), true, &errorMessage), errorMessage.constData());
window.show();
window.requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickItem *root = window.rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea*>("mouseArea");
- QVERIFY(mouseArea != 0);
+ QVERIFY(mouseArea != nullptr);
QSignalSpy containsPressSpy(mouseArea, SIGNAL(containsPressChanged()));
@@ -2006,7 +2028,7 @@ void tst_QQuickMouseArea::ignoreBySource()
{
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("ignoreBySource.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("ignoreBySource.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QVERIFY(window.rootObject());
@@ -2022,7 +2044,7 @@ void tst_QQuickMouseArea::ignoreBySource()
// MouseArea should grab the press because it's interested in non-synthesized mouse events
QPoint p = QPoint(80, 80);
- QTest::mousePress(&window, Qt::LeftButton, 0, p);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
QCOMPARE(window.mouseGrabberItem(), mouseArea);
// That was a real mouse event
QCOMPARE(root->property("lastEventSource").toInt(), int(Qt::MouseEventNotSynthesized));
@@ -2037,7 +2059,7 @@ void tst_QQuickMouseArea::ignoreBySource()
QCOMPARE(flickable->contentX(), 0.);
QCOMPARE(flickable->contentY(), 0.);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, p);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p);
QCOMPARE(window.mouseGrabberItem(), nullptr);
// Now try touch events and confirm that MouseArea ignores them, while Flickable does its thing
@@ -2073,7 +2095,7 @@ void tst_QQuickMouseArea::ignoreBySource()
// MouseArea should ignore the press because it's interested in synthesized mouse events
p = QPoint(80, 80);
- QTest::mousePress(&window, Qt::LeftButton, 0, p);
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p);
QVERIFY(window.mouseGrabberItem() != mouseArea);
// That was a real mouse event
QVERIFY(root->property("lastEventSource").toInt() == Qt::MouseEventNotSynthesized);
@@ -2088,7 +2110,7 @@ void tst_QQuickMouseArea::ignoreBySource()
QTRY_VERIFY(flickable->contentX() > 1);
QVERIFY(flickable->contentY() > 1);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(47, 47));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(47, 47));
flickable->setContentX(0);
flickable->setContentY(0);
@@ -2118,7 +2140,7 @@ void tst_QQuickMouseArea::notPressedAfterStolenGrab()
QQuickWindow window;
window.resize(200, 200);
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickMouseArea *ma = new QQuickMouseArea(window.contentItem());
ma->setSize(window.size());
@@ -2147,15 +2169,15 @@ void tst_QQuickMouseArea::pressAndHold()
QQuickView window;
QByteArray errorMessage;
- QVERIFY2(initView(window, testFileUrl("pressAndHold.qml"), true, &errorMessage), errorMessage.constData());
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("pressAndHold.qml"), true, &errorMessage), errorMessage.constData());
window.show();
window.requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickItem *root = window.rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea*>("mouseArea");
- QVERIFY(mouseArea != 0);
+ QVERIFY(mouseArea != nullptr);
QSignalSpy pressAndHoldSpy(mouseArea, &QQuickMouseArea::pressAndHold);
@@ -2173,6 +2195,117 @@ void tst_QQuickMouseArea::pressAndHold()
QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
}
+void tst_QQuickMouseArea::pressOneAndTapAnother_data()
+{
+ QTest::addColumn<bool>("pressMouseFirst");
+ QTest::addColumn<bool>("releaseMouseFirst");
+
+ QTest::newRow("press mouse, tap touch, release mouse") << true << false; // QTBUG-64249 as written
+ QTest::newRow("press touch, press mouse, release touch, release mouse") << false << false;
+ QTest::newRow("press mouse, press touch, release mouse, release touch") << true << true;
+ // TODO fix in a separate patch after the 5.9->5.10 merge
+ // QTest::newRow("press touch, click mouse, release touch") << false << true;
+}
+
+void tst_QQuickMouseArea::pressOneAndTapAnother()
+{
+ QFETCH(bool, pressMouseFirst);
+ QFETCH(bool, releaseMouseFirst);
+
+ QQuickView window;
+ QByteArray errorMessage;
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("twoMouseAreas.qml"), true, &errorMessage), errorMessage.constData());
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QQuickItem *root = window.rootObject();
+ QVERIFY(root);
+ QQuickMouseArea *bottomMA = window.rootObject()->findChild<QQuickMouseArea*>("bottom");
+ QVERIFY(bottomMA);
+ QQuickMouseArea *topMA = window.rootObject()->findChild<QQuickMouseArea*>("top");
+ QVERIFY(topMA);
+
+ QPoint upper(32, 32);
+ QPoint lower(32, window.height() - 32);
+
+ // press them both
+ if (pressMouseFirst) {
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, lower);
+ QTRY_COMPARE(bottomMA->pressed(), true);
+
+ QTest::touchEvent(&window, device).press(0, lower, &window);
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE(bottomMA->pressed(), true);
+ } else {
+ QTest::touchEvent(&window, device).press(0, lower, &window);
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE(bottomMA->pressed(), true);
+
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, lower);
+ QTRY_COMPARE(bottomMA->pressed(), true);
+ }
+
+ // release them both and make sure neither one gets stuck
+ if (releaseMouseFirst) {
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, lower);
+ QTRY_COMPARE(bottomMA->pressed(), false);
+
+ QTest::touchEvent(&window, device).release(0, upper, &window);
+ QQuickTouchUtils::flush(&window);
+ QTRY_COMPARE(topMA->pressed(), false);
+ } else {
+ QTest::touchEvent(&window, device).release(0, upper, &window);
+ QQuickTouchUtils::flush(&window);
+
+ QTRY_COMPARE(topMA->pressed(), false);
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, lower);
+ QTRY_COMPARE(bottomMA->pressed(), false);
+ }
+}
+
+void tst_QQuickMouseArea::mask()
+{
+ QQuickView window;
+ QByteArray errorMessage;
+ QVERIFY2(QQuickTest::initView(window, testFileUrl("mask.qml"), true, &errorMessage), errorMessage.constData());
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QQuickItem *root = window.rootObject();
+ QVERIFY(root != nullptr);
+
+ // click inside the mask, and verify it registers
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100,100));
+
+ QCOMPARE(window.rootObject()->property("pressed").toInt(), 1);
+ QCOMPARE(window.rootObject()->property("released").toInt(), 1);
+ QCOMPARE(window.rootObject()->property("clicked").toInt(), 1);
+
+ // click outside the mask (but inside the MouseArea), and verify it doesn't register
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
+
+ QCOMPARE(window.rootObject()->property("pressed").toInt(), 1);
+ QCOMPARE(window.rootObject()->property("released").toInt(), 1);
+ QCOMPARE(window.rootObject()->property("clicked").toInt(), 1);
+}
+
+void tst_QQuickMouseArea::nestedEventDelivery() // QTBUG-70898
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("nestedSendEvent.qml"));
+ QScopedPointer<QQuickWindow> window(qmlobject_cast<QQuickWindow *>(c.create()));
+ QVERIFY(window.data());
+
+ // Click each MouseArea and verify that it doesn't crash
+ QByteArray message = "event went missing during delivery! (nested sendEvent() is not allowed)";
+ QTest::ignoreMessage(QtWarningMsg, message);
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
+ QTest::ignoreMessage(QtWarningMsg, message); // twice though, actually
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50,150));
+}
+
QTEST_MAIN(tst_QQuickMouseArea)
#include "tst_qquickmousearea.moc"
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
index cab6e2f7bf..cdb3e7733b 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
+++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
@@ -1,4 +1,6 @@
[nonOverlapping]
ubuntu-16.04
+ubuntu-18.04
[nested]
ubuntu-16.04
+ubuntu-18.04
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml b/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml
index 0abcc76f7c..b0410dac4a 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/mouse.qml
@@ -6,6 +6,9 @@ MultiPointTouchArea {
property int touchCount: 0
property int cancelCount: 0
+ property int gestureStartedX: 0
+ property int gestureStartedY: 0
+ property bool grabGesture: false
minimumTouchPoints: 1
maximumTouchPoints: 4
@@ -17,6 +20,12 @@ MultiPointTouchArea {
onPressed: { touchCount = touchPoints.length }
onTouchUpdated: { touchCount = touchPoints.length }
onCanceled: { cancelCount = touchPoints.length }
+ onGestureStarted: {
+ gestureStartedX = gesture.touchPoints[0].startX
+ gestureStartedY = gesture.touchPoints[0].startY
+ if (grabGesture)
+ gesture.grab()
+ }
Rectangle {
color: "red"
diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml
index 039607e26c..027f90c7f4 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml
+++ b/tests/auto/quick/qquickmultipointtoucharea/data/nonOverlapping.qml
@@ -11,9 +11,21 @@ Rectangle {
maximumTouchPoints: 2
onGestureStarted: gesture.grab()
touchPoints: [
- TouchPoint { objectName: "point11" },
- TouchPoint { objectName: "point12" }
+ TouchPoint { id: point11; objectName: "point11" },
+ TouchPoint { id: point12; objectName: "point12" }
]
+ Rectangle {
+ color: "red"
+ width: 10; height: 10; radius: 5
+ x: point11.x - radius; y: point11.y - radius
+ visible: point11.pressed
+ }
+ Rectangle {
+ color: "tomato"
+ width: 10; height: 10; radius: 5
+ x: point12.x - radius; y: point12.y - radius
+ visible: point12.pressed
+ }
}
MultiPointTouchArea {
@@ -24,9 +36,27 @@ Rectangle {
maximumTouchPoints: 3
onGestureStarted: gesture.grab()
touchPoints: [
- TouchPoint { objectName: "point21" },
- TouchPoint { objectName: "point22" },
- TouchPoint { objectName: "point23" }
+ TouchPoint { id: point21; objectName: "point21" },
+ TouchPoint { id: point22; objectName: "point22" },
+ TouchPoint { id: point23; objectName: "point23" }
]
+ Rectangle {
+ color: "lightgreen"
+ width: 10; height: 10; radius: 5
+ x: point21.x - radius; y: point21.y - radius
+ visible: point21.pressed
+ }
+ Rectangle {
+ color: "green"
+ width: 10; height: 10; radius: 5
+ x: point22.x - radius; y: point22.y - radius
+ visible: point22.pressed
+ }
+ Rectangle {
+ color: "darkgreen"
+ width: 10; height: 10; radius: 5
+ x: point23.x - radius; y: point23.y - radius
+ visible: point23.pressed
+ }
}
}
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index 87acd67f6a..d4ad282701 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -41,7 +41,7 @@ class tst_QQuickMultiPointTouchArea : public QQmlDataTest
{
Q_OBJECT
public:
- tst_QQuickMultiPointTouchArea() : device(0) { }
+ tst_QQuickMultiPointTouchArea() { }
private slots:
void initTestCase() {
@@ -69,20 +69,22 @@ private slots:
void transformedTouchArea();
void mouseInteraction();
void mouseInteraction_data();
+ void mouseGestureStarted_data();
+ void mouseGestureStarted();
void cancel();
private:
QQuickView *createAndShowView(const QString &file);
- QTouchDevice *device;
+ QTouchDevice *device = nullptr;
};
void tst_QQuickMultiPointTouchArea::properties()
{
QScopedPointer<QQuickView> window(createAndShowView("properties.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(window->rootObject());
- QVERIFY(area != 0);
+ QVERIFY(area != nullptr);
QCOMPARE(area->minimumTouchPoints(), 2);
QCOMPARE(area->maximumTouchPoints(), 4);
@@ -94,10 +96,10 @@ void tst_QQuickMultiPointTouchArea::properties()
void tst_QQuickMultiPointTouchArea::signalTest()
{
QScopedPointer<QQuickView> window(createAndShowView("signalTest.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(window->rootObject());
- QVERIFY(area != 0);
+ QVERIFY(area != nullptr);
QPoint p1(20,100);
QPoint p2(40,100);
@@ -161,7 +163,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
void tst_QQuickMultiPointTouchArea::release()
{
QScopedPointer<QQuickView> window(createAndShowView("basic.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickTouchPoint *point1 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
@@ -197,7 +199,7 @@ void tst_QQuickMultiPointTouchArea::release()
void tst_QQuickMultiPointTouchArea::reuse()
{
QScopedPointer<QQuickView> window(createAndShowView("basic.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickTouchPoint *point1 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
QQuickTouchPoint *point2 = window->rootObject()->findChild<QQuickTouchPoint*>("point2");
@@ -264,7 +266,7 @@ void tst_QQuickMultiPointTouchArea::reuse()
void tst_QQuickMultiPointTouchArea::nonOverlapping()
{
QScopedPointer<QQuickView> window(createAndShowView("nonOverlapping.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point11");
QQuickTouchPoint *point12 = window->rootObject()->findChild<QQuickTouchPoint*>("point12");
@@ -378,7 +380,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
void tst_QQuickMultiPointTouchArea::nested()
{
QScopedPointer<QQuickView> window(createAndShowView("nested.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point11");
QQuickTouchPoint *point12 = window->rootObject()->findChild<QQuickTouchPoint*>("point12");
@@ -574,13 +576,13 @@ void tst_QQuickMultiPointTouchArea::nested()
void tst_QQuickMultiPointTouchArea::inFlickable()
{
QScopedPointer<QQuickView> window(createAndShowView("inFlickable.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
- QVERIFY(mpta != 0);
+ QVERIFY(mpta != nullptr);
QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
QQuickTouchPoint *point12 = window->rootObject()->findChild<QQuickTouchPoint*>("point2");
@@ -623,7 +625,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
//moving two points vertically
p1 = QPoint(20,100);
QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
@@ -658,7 +660,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QCOMPARE(flickable->property("touchCount").toInt(), 0);
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
QQuickTouchUtils::flush(window.data());
QTRY_VERIFY(!flickable->isMoving());
@@ -670,7 +672,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QQuickTouchUtils::flush(window.data());
// ensure that mouse events do not fall through to the Flickable
mpta->setMaximumTouchPoints(3);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -720,7 +722,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QCOMPARE(point12->pressed(), true);
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
QQuickTouchUtils::flush(window.data());
}
@@ -728,10 +730,10 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
void tst_QQuickMultiPointTouchArea::inFlickable2()
{
QScopedPointer<QQuickView> window(createAndShowView("inFlickable2.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
QVERIFY(point11);
@@ -743,7 +745,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
// move point horizontally, out of Flickable area
QTest::touchEvent(window.data(), device).press(0, p1);
QQuickTouchUtils::flush(window.data());
- QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
@@ -770,7 +772,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
QTest::touchEvent(window.data(), device).release(0, p1);
QQuickTouchUtils::flush(window.data());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
QTest::qWait(50);
QTRY_VERIFY(!flickable->isMoving());
@@ -813,13 +815,13 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
void tst_QQuickMultiPointTouchArea::inMouseArea()
{
QScopedPointer<QQuickView> window(createAndShowView("inMouseArea.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickMouseArea *mouseArea = qobject_cast<QQuickMouseArea *>(window->rootObject());
- QVERIFY(mouseArea != 0);
+ QVERIFY(mouseArea != nullptr);
QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>("mpta");
- QVERIFY(mpta != 0);
+ QVERIFY(mpta != nullptr);
QPoint innerPoint(40,100);
QPoint outerPoint(10,100);
@@ -829,15 +831,15 @@ void tst_QQuickMultiPointTouchArea::inMouseArea()
QTest::touchEvent(window.data(), device).release(0, innerPoint);
QVERIFY(!mpta->property("pressed").toBool());
- QTest::mousePress(window.data(), Qt::LeftButton, 0, outerPoint);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, outerPoint);
QVERIFY(mouseArea->property("pressed").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, outerPoint);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, outerPoint);
QVERIFY(!mouseArea->property("pressed").toBool());
- QTest::mousePress(window.data(), Qt::LeftButton, 0, innerPoint);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, innerPoint);
QVERIFY(mpta->property("pressed").toBool());
QVERIFY(!mouseArea->property("pressed").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, innerPoint);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, innerPoint);
QVERIFY(!mpta->property("pressed").toBool());
QVERIFY(!mouseArea->property("pressed").toBool());
@@ -854,10 +856,10 @@ void tst_QQuickMultiPointTouchArea::inMouseArea()
QVERIFY(!mpta->property("pressed").toBool());
// Right click should pass through
- QTest::mousePress(window.data(), Qt::RightButton, 0, innerPoint);
+ QTest::mousePress(window.data(), Qt::RightButton, Qt::NoModifier, innerPoint);
QVERIFY(mouseArea->property("pressed").toBool());
QVERIFY(!mpta->property("pressed").toBool());
- QTest::mouseRelease(window.data(), Qt::RightButton, 0, innerPoint);
+ QTest::mouseRelease(window.data(), Qt::RightButton, Qt::NoModifier, innerPoint);
mpta->setProperty("mouseEnabled", false);
@@ -868,15 +870,15 @@ void tst_QQuickMultiPointTouchArea::inMouseArea()
QVERIFY(!mpta->property("pressed").toBool());
QVERIFY(!mouseArea->property("pressed").toBool());
- QTest::mousePress(window.data(), Qt::LeftButton, 0, outerPoint);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, outerPoint);
QVERIFY(mouseArea->property("pressed").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, outerPoint);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, outerPoint);
QVERIFY(!mouseArea->property("pressed").toBool());
- QTest::mousePress(window.data(), Qt::LeftButton, 0, innerPoint);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, innerPoint);
QVERIFY(!mpta->property("pressed").toBool());
QVERIFY(mouseArea->property("pressed").toBool());
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, innerPoint);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, innerPoint);
QVERIFY(!mpta->property("pressed").toBool());
QVERIFY(!mouseArea->property("pressed").toBool());
@@ -896,10 +898,10 @@ void tst_QQuickMultiPointTouchArea::inMouseArea()
void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
{
QScopedPointer<QQuickView> window(createAndShowView("dualGestures.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickMultiPointTouchArea *dualmpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>("dualTouchArea");
- QVERIFY(dualmpta != 0);
+ QVERIFY(dualmpta != nullptr);
QQuickItem *touch1rect = window->rootObject()->findChild<QQuickItem*>("touch1rect");
QQuickItem *touch2rect = window->rootObject()->findChild<QQuickItem*>("touch2rect");
@@ -923,18 +925,18 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
QTest::touchEvent(window.data(), device).release(1, touch1).move(2, touch2);
touch1.setY(20);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, touch1);
QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
QTest::touchEvent(window.data(), device).release(2, touch2);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, touch1);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, touch1);
QQuickTouchUtils::flush(window.data());
// Start with mouse, move it, touch second point, move it
- QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, touch1);
touch1.setX(60);
QTest::mouseMove(window.data(), touch1);
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
@@ -963,7 +965,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
// Release all
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, touch1);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, touch1);
QTest::touchEvent(window.data(), device).release(3, touch2);
QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).release(4, touch3);
@@ -982,7 +984,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QPoint touch3(340,100);
QPoint touch4(540,10);
- QTest::mousePress(window.data(), Qt::LeftButton, 0, mouse1);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, mouse1);
QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
QTest::touchEvent(window.data(), device).press(1, touch1);
@@ -1006,7 +1008,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch5rect->property("y").toInt(), touch4.y());
// Release all
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, mouse1);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, mouse1);
QTest::touchEvent(window.data(), device).release(1, touch1).release(2, touch2).release(3, touch3).release(4, touch4);
QQuickTouchUtils::flush(window.data());
}
@@ -1024,7 +1026,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Start with mouse, move it, touch a point, move it, touch another.
// Mouse is ignored, both touch points are heeded.
- QTest::mousePress(window.data(), Qt::LeftButton, 0, mouse1);
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, mouse1);
mouse1.setX(60);
QTest::mouseMove(window.data(), mouse1);
QCOMPARE(touch1rect->property("x").toInt(), 10);
@@ -1047,7 +1049,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
// Release all
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, mouse1);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, mouse1);
QTest::touchEvent(window.data(), device).release(1, touch1);
QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).release(2, touch2);
@@ -1063,10 +1065,10 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
void tst_QQuickMultiPointTouchArea::invisible()
{
QScopedPointer<QQuickView> window(createAndShowView("signalTest.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(window->rootObject());
- QVERIFY(area != 0);
+ QVERIFY(area != nullptr);
area->setVisible(false);
@@ -1124,10 +1126,10 @@ void tst_QQuickMultiPointTouchArea::transformedTouchArea()
QScopedPointer<QQuickView> view(createAndShowView("transformedMultiPointTouchArea.qml"));
- QVERIFY(view->rootObject() != 0);
+ QVERIFY(view->rootObject() != nullptr);
QQuickMultiPointTouchArea *area = view->rootObject()->findChild<QQuickMultiPointTouchArea *>("touchArea");
- QVERIFY(area != 0);
+ QVERIFY(area != nullptr);
QTest::QTouchEventSequence sequence = QTest::touchEvent(view.data(), device);
@@ -1143,7 +1145,7 @@ void tst_QQuickMultiPointTouchArea::transformedTouchArea()
QQuickView *tst_QQuickMultiPointTouchArea::createAndShowView(const QString &file)
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl(file));
const QRect screenGeometry = window->screen()->availableGeometry();
const QSize size = window->size();
@@ -1171,16 +1173,16 @@ void tst_QQuickMultiPointTouchArea::mouseInteraction()
QFETCH(int, accept);
QScopedPointer<QQuickView> view(createAndShowView("mouse.qml"));
- QVERIFY(view->rootObject() != 0);
+ QVERIFY(view->rootObject() != nullptr);
QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(view->rootObject());
- QVERIFY(area != 0);
+ QVERIFY(area != nullptr);
QQuickTouchPoint *point1 = view->rootObject()->findChild<QQuickTouchPoint*>("point1");
QCOMPARE(point1->pressed(), false);
QCOMPARE(area->property("touchCount").toInt(), 0);
QPoint p1 = QPoint(100, 100);
- QTest::mousePress(view.data(), (Qt::MouseButton) buttons, 0, p1);
+ QTest::mousePress(view.data(), (Qt::MouseButton) buttons, Qt::NoModifier, p1);
QCOMPARE(area->property("touchCount").toInt(), accept);
QCOMPARE(point1->pressed(), accept != 0);
p1 += QPoint(10, 10);
@@ -1196,10 +1198,61 @@ void tst_QQuickMultiPointTouchArea::mouseInteraction()
QCOMPARE(area->property("touchCount").toInt(), 0);
}
+void tst_QQuickMultiPointTouchArea::mouseGestureStarted_data()
+{
+ QTest::addColumn<bool>("grabGesture");
+ QTest::addColumn<int>("distanceFromOrigin");
+
+ QTest::newRow("near origin, don't grab") << false << 4;
+ QTest::newRow("near origin, grab") << true << 4;
+ QTest::newRow("away from origin, don't grab") << false << 100;
+ QTest::newRow("away from origin, grab") << true << 100;
+}
+
+void tst_QQuickMultiPointTouchArea::mouseGestureStarted() // QTBUG-70258
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QFETCH(bool, grabGesture);
+ QFETCH(int, distanceFromOrigin);
+
+ QScopedPointer<QQuickView> view(createAndShowView("mouse.qml"));
+ QVERIFY(view->rootObject() != nullptr);
+
+ QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(view->rootObject());
+ QVERIFY(area);
+ area->setProperty("grabGesture", grabGesture);
+ QQuickTouchPoint *point1 = view->rootObject()->findChild<QQuickTouchPoint*>("point1");
+ QCOMPARE(point1->pressed(), false);
+ QSignalSpy gestureStartedSpy(area, SIGNAL(gestureStarted(QQuickGrabGestureEvent *)));
+
+ QPoint p1 = QPoint(distanceFromOrigin, distanceFromOrigin);
+ QTest::mousePress(view.data(), Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(gestureStartedSpy.count(), 0);
+
+ p1 += QPoint(dragThreshold, dragThreshold);
+ QTest::mouseMove(view.data(), p1);
+ QCOMPARE(gestureStartedSpy.count(), 0);
+
+ p1 += QPoint(1, 1);
+ QTest::mouseMove(view.data(), p1);
+ QTRY_COMPARE(gestureStartedSpy.count(), 1);
+ QTRY_COMPARE(area->property("gestureStartedX").toInt(), distanceFromOrigin);
+ QCOMPARE(area->property("gestureStartedY").toInt(), distanceFromOrigin);
+
+ p1 += QPoint(10, 10);
+ QTest::mouseMove(view.data(), p1);
+ // if nobody called gesteure->grab(), gestureStarted will keep happening
+ QTRY_COMPARE(gestureStartedSpy.count(), grabGesture ? 1 : 2);
+ QCOMPARE(area->property("gestureStartedX").toInt(), distanceFromOrigin);
+ QCOMPARE(area->property("gestureStartedY").toInt(), distanceFromOrigin);
+
+ QTest::mouseRelease(view.data(), Qt::LeftButton);
+}
+
void tst_QQuickMultiPointTouchArea::cancel()
{
QScopedPointer<QQuickView> window(createAndShowView("cancel.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickMultiPointTouchArea *area = qobject_cast<QQuickMultiPointTouchArea *>(window->rootObject());
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
diff --git a/tests/auto/quick/qquickopenglinfo/BLACKLIST b/tests/auto/quick/qquickopenglinfo/BLACKLIST
new file mode 100644
index 0000000000..7ac31e1cd0
--- /dev/null
+++ b/tests/auto/quick/qquickopenglinfo/BLACKLIST
@@ -0,0 +1,3 @@
+# QTBUG-65615
+[testProperties]
+b2qt
diff --git a/tests/auto/quick/qquickpainteditem/BLACKLIST b/tests/auto/quick/qquickpainteditem/BLACKLIST
new file mode 100644
index 0000000000..9b58325f6c
--- /dev/null
+++ b/tests/auto/quick/qquickpainteditem/BLACKLIST
@@ -0,0 +1,27 @@
+# QTBUG-63053
+[opaquePainting]
+b2qt
+
+# QTBUG-63053
+[antialiasing]
+b2qt
+
+# QTBUG-63053
+[mipmap]
+b2qt
+
+# QTBUG-63053
+[performanceHints]
+b2qt
+
+# QTBUG-63053
+[contentScale]
+b2qt
+
+# QTBUG-63053
+[contentsBoundingRect]
+b2qt
+
+# QTBUG-63053
+[fillColor]
+b2qt
diff --git a/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp b/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp
index 1716bdeafb..2661762669 100644
--- a/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp
+++ b/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp
@@ -61,9 +61,9 @@ class TestPaintedItem : public QQuickPaintedItem
{
Q_OBJECT
public:
- TestPaintedItem(QQuickItem *parent = 0)
+ TestPaintedItem(QQuickItem *parent = nullptr)
: QQuickPaintedItem(parent)
- , paintNode(0)
+ , paintNode(nullptr)
, paintRequests(0)
{
}
diff --git a/tests/auto/quick/qquickpath/data/anglearc.qml b/tests/auto/quick/qquickpath/data/anglearc.qml
new file mode 100644
index 0000000000..cbe41c1ac8
--- /dev/null
+++ b/tests/auto/quick/qquickpath/data/anglearc.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.11
+
+Path {
+ PathAngleArc {
+ centerX: 100
+ centerY: 100
+ radiusX: 50
+ radiusY: 50
+ startAngle: 45
+ sweepAngle: 90
+ }
+}
diff --git a/tests/auto/quick/qquickpath/tst_qquickpath.cpp b/tests/auto/quick/qquickpath/tst_qquickpath.cpp
index 2ec95840e1..12a8c673b0 100644
--- a/tests/auto/quick/qquickpath/tst_qquickpath.cpp
+++ b/tests/auto/quick/qquickpath/tst_qquickpath.cpp
@@ -41,6 +41,7 @@ public:
private slots:
void arc();
+ void angleArc();
void catmullromCurve();
void closedCatmullromCurve();
void svg();
@@ -52,7 +53,7 @@ void tst_QuickPath::arc()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("arc.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->startX(), 0.);
QCOMPARE(obj->startY(), 0.);
@@ -61,7 +62,7 @@ void tst_QuickPath::arc()
QCOMPARE(list.count(), 1);
QQuickPathArc* arc = qobject_cast<QQuickPathArc*>(list.at(0));
- QVERIFY(arc != 0);
+ QVERIFY(arc != nullptr);
QCOMPARE(arc->x(), 100.);
QCOMPARE(arc->y(), 100.);
QCOMPARE(arc->radiusX(), 100.);
@@ -82,12 +83,51 @@ void tst_QuickPath::arc()
QCOMPARE(pos, QPointF(100,100));
}
+void tst_QuickPath::angleArc()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("anglearc.qml"));
+ QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
+ QVERIFY(obj != nullptr);
+
+ QQmlListReference list(obj, "pathElements");
+ QCOMPARE(list.count(), 1);
+
+ QQuickPathAngleArc* arc = qobject_cast<QQuickPathAngleArc*>(list.at(0));
+ QVERIFY(arc != nullptr);
+ QCOMPARE(arc->centerX(), 100.);
+ QCOMPARE(arc->centerY(), 100.);
+ QCOMPARE(arc->radiusX(), 50.);
+ QCOMPARE(arc->radiusY(), 50.);
+ QCOMPARE(arc->startAngle(), 45.);
+ QCOMPARE(arc->sweepAngle(), 90.);
+ QCOMPARE(arc->moveToStart(), true);
+
+ QPainterPath path = obj->path();
+ QVERIFY(path != QPainterPath());
+
+ // using QPoint to do fuzzy compare
+ QPointF pos = obj->pointAt(0);
+ QCOMPARE(pos.toPoint(), QPoint(135,135));
+ pos = obj->pointAt(.25);
+ QCOMPARE(pos.toPoint(), QPoint(119,146));
+ pos = obj->pointAt(.75);
+ QCOMPARE(pos.toPoint(), QPoint(81,146));
+ pos = obj->pointAt(1);
+ QCOMPARE(pos.toPoint(), QPoint(65,135));
+
+ // if moveToStart is false, we should have a line starting from startX/Y
+ arc->setMoveToStart(false);
+ pos = obj->pointAt(0);
+ QCOMPARE(pos, QPointF(0,0));
+}
+
void tst_QuickPath::catmullromCurve()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("curve.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->startX(), 0.);
QCOMPARE(obj->startY(), 0.);
@@ -96,12 +136,12 @@ void tst_QuickPath::catmullromCurve()
QCOMPARE(list.count(), 3);
QQuickPathCatmullRomCurve* curve = qobject_cast<QQuickPathCatmullRomCurve*>(list.at(0));
- QVERIFY(curve != 0);
+ QVERIFY(curve != nullptr);
QCOMPARE(curve->x(), 100.);
QCOMPARE(curve->y(), 50.);
curve = qobject_cast<QQuickPathCatmullRomCurve*>(list.at(2));
- QVERIFY(curve != 0);
+ QVERIFY(curve != nullptr);
QCOMPARE(curve->x(), 100.);
QCOMPARE(curve->y(), 150.);
@@ -123,7 +163,7 @@ void tst_QuickPath::closedCatmullromCurve()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("closedcurve.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->startX(), 50.);
QCOMPARE(obj->startY(), 50.);
@@ -132,7 +172,7 @@ void tst_QuickPath::closedCatmullromCurve()
QCOMPARE(list.count(), 3);
QQuickPathCatmullRomCurve* curve = qobject_cast<QQuickPathCatmullRomCurve*>(list.at(2));
- QVERIFY(curve != 0);
+ QVERIFY(curve != nullptr);
QCOMPARE(curve->x(), 50.);
QCOMPARE(curve->y(), 50.);
@@ -156,7 +196,7 @@ void tst_QuickPath::svg()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("svg.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->startX(), 0.);
QCOMPARE(obj->startY(), 0.);
@@ -165,7 +205,7 @@ void tst_QuickPath::svg()
QCOMPARE(list.count(), 1);
QQuickPathSvg* svg = qobject_cast<QQuickPathSvg*>(list.at(0));
- QVERIFY(svg != 0);
+ QVERIFY(svg != nullptr);
QCOMPARE(svg->path(), QLatin1String("M200,300 Q400,50 600,300 T1000,300"));
QPainterPath path = obj->path();
diff --git a/tests/auto/quick/qquickpathview/data/flickableDelegate.qml b/tests/auto/quick/qquickpathview/data/flickableDelegate.qml
index df9cb1d547..0304efaa31 100644
--- a/tests/auto/quick/qquickpathview/data/flickableDelegate.qml
+++ b/tests/auto/quick/qquickpathview/data/flickableDelegate.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquickpathview/data/nestedInFlickable.qml b/tests/auto/quick/qquickpathview/data/nestedInFlickable.qml
index ec1f3235c3..216a25b8e2 100644
--- a/tests/auto/quick/qquickpathview/data/nestedInFlickable.qml
+++ b/tests/auto/quick/qquickpathview/data/nestedInFlickable.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquickpathview/data/objectModelMove.qml b/tests/auto/quick/qquickpathview/data/objectModelMove.qml
new file mode 100644
index 0000000000..d5fa510d69
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/objectModelMove.qml
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "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 COPYRIGHT
+** OWNER OR CONTRIBUTORS 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml.Models 2.11
+import QtQuick 2.11
+
+Item {
+ id: root
+ width: 400
+ height: 400
+ visible: true
+
+ property Item pathViewItem
+
+ function destroyView() {
+ if (pathViewItem)
+ pathViewItem.destroy()
+ }
+
+ function newView() {
+ pathViewItem = pathViewComponent.createObject(root)
+ }
+
+ function move() {
+ objectModel.move(0, 1)
+ }
+
+ Component {
+ id: pathViewComponent
+
+ PathView {
+ id: pathView
+ objectName: "PathView"
+ width: 32 * 3
+ height: 32
+ model: objectModel
+
+ interactive: false
+ snapMode: PathView.SnapToItem
+ movementDirection: PathView.Positive
+ highlightMoveDuration: 100
+
+ path: Path {
+ startX: 16
+ startY: 16
+ PathLine {
+ x: 16 + (32 * 3)
+ y: 16
+ }
+ }
+ }
+ }
+
+ ObjectModel {
+ id: objectModel
+
+ Rectangle {
+ objectName: "red"
+ width: 32
+ height: 32
+ color: "red"
+ }
+ Rectangle {
+ objectName: "green"
+ width: 32
+ height: 32
+ color: "green"
+ }
+ Rectangle {
+ objectName: "blue"
+ width: 32
+ height: 32
+ color: "blue"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/data/panels.qml b/tests/auto/quick/qquickpathview/data/panels.qml
index a111e45736..08e4636dca 100644
--- a/tests/auto/quick/qquickpathview/data/panels.qml
+++ b/tests/auto/quick/qquickpathview/data/panels.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Item {
id: root
@@ -6,7 +7,7 @@ Item {
property bool enforceRange: false
width: 320; height: 480
- VisualItemModel {
+ ObjectModel {
id: itemModel
Rectangle {
diff --git a/tests/auto/quick/qquickpathview/data/pathview_package.qml b/tests/auto/quick/qquickpathview/data/pathview_package.qml
index 2af57e6bb1..34d4ee73ba 100644
--- a/tests/auto/quick/qquickpathview/data/pathview_package.qml
+++ b/tests/auto/quick/qquickpathview/data/pathview_package.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Item {
width: 800; height: 600
@@ -37,7 +38,7 @@ Item {
ListElement { lColor: "brown" }
ListElement { lColor: "thistle" }
}
- VisualDataModel { id: visualModel; model: rssModel; delegate: photoDelegate }
+ DelegateModel { id: visualModel; model: rssModel; delegate: photoDelegate }
PathView {
id: photoPathView
diff --git a/tests/auto/quick/qquickpathview/data/qtbug37815.qml b/tests/auto/quick/qquickpathview/data/qtbug37815.qml
index 3fd4daca63..28affbac38 100644
--- a/tests/auto/quick/qquickpathview/data/qtbug37815.qml
+++ b/tests/auto/quick/qquickpathview/data/qtbug37815.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
** Copyright (C) 2016 Netris
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquickpathview/data/qtbug53464.qml b/tests/auto/quick/qquickpathview/data/qtbug53464.qml
index d30d404e68..123cafb04c 100644
--- a/tests/auto/quick/qquickpathview/data/qtbug53464.qml
+++ b/tests/auto/quick/qquickpathview/data/qtbug53464.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
** Copyright (C) 2016 Netris
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquickpathview/data/removePath.qml b/tests/auto/quick/qquickpathview/data/removePath.qml
index 85029f3eaf..36343adaaf 100644
--- a/tests/auto/quick/qquickpathview/data/removePath.qml
+++ b/tests/auto/quick/qquickpathview/data/removePath.qml
@@ -6,7 +6,7 @@ PathView {
path: myPath
- delegate: Text { text: value }
+ delegate: Text { text: modelData }
model: 10
Path {
diff --git a/tests/auto/quick/qquickpathview/data/treemodel.qml b/tests/auto/quick/qquickpathview/data/treemodel.qml
index fcf6922d00..b1e06f47d2 100644
--- a/tests/auto/quick/qquickpathview/data/treemodel.qml
+++ b/tests/auto/quick/qquickpathview/data/treemodel.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
PathView {
width: 320
@@ -6,7 +7,7 @@ PathView {
function setRoot(index) {
vdm.rootIndex = vdm.modelIndex(index);
}
- model: VisualDataModel {
+ model: DelegateModel {
id: vdm
model: myModel
delegate: Text { objectName: "wrapper"; text: display }
diff --git a/tests/auto/quick/qquickpathview/data/vdm.qml b/tests/auto/quick/qquickpathview/data/vdm.qml
index 839393d9bd..f24837b7a6 100644
--- a/tests/auto/quick/qquickpathview/data/vdm.qml
+++ b/tests/auto/quick/qquickpathview/data/vdm.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
PathView {
id: pathView
@@ -20,7 +21,7 @@ PathView {
ListElement { value: "three" }
}
- model: VisualDataModel {
+ model: DelegateModel {
delegate: Text { text: model.value }
model : mo
}
diff --git a/tests/auto/quick/qquickpathview/qquickpathview.pro b/tests/auto/quick/qquickpathview/qquickpathview.pro
index 90c1eb0c67..f21fb64fa4 100644
--- a/tests/auto/quick/qquickpathview/qquickpathview.pro
+++ b/tests/auto/quick/qquickpathview/qquickpathview.pro
@@ -9,5 +9,5 @@ include (../shared/util.pri)
TESTDATA = data/*
-QT += core-private gui-private qml-private quick-private testlib
+QT += core-private gui-private qml-private quick-private testlib qmltest
qtHaveModule(widgets): QT += widgets
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index b01d0c3cec..bf38d2d926 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -38,6 +38,7 @@
#include <QtQuick/private/qquickpath_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuickTest/QtQuickTest>
#include <QtQml/private/qqmllistmodel_p.h>
#include <QtQml/private/qqmlvaluetype_p.h>
#include <QtGui/qstandarditemmodel.h>
@@ -48,6 +49,10 @@
#include "../shared/viewtestutil.h"
#include "../shared/visualtestutil.h"
+#include <math.h>
+
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
using namespace QQuickViewTestUtil;
using namespace QQuickVisualTestUtil;
@@ -142,6 +147,7 @@ private slots:
void movementDirection_data();
void movementDirection();
void removePath();
+ void objectModelMove();
};
class TestObject : public QObject
@@ -184,7 +190,7 @@ void tst_QQuickPathView::initValues()
QQmlComponent c(&engine, testFileUrl("pathview1.qml"));
QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QVERIFY(!obj->path());
QVERIFY(!obj->delegate());
QCOMPARE(obj->model(), QVariant());
@@ -215,7 +221,7 @@ void tst_QQuickPathView::items()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QCOMPARE(pathview->count(), model.count());
QCOMPARE(window->rootObject()->property("count").toInt(), model.count());
@@ -223,10 +229,10 @@ void tst_QQuickPathView::items()
for (int i = 0; i < model.count(); ++i) {
QQuickText *name = findItem<QQuickText>(pathview, "textName", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), model.name(i));
QQuickText *number = findItem<QQuickText>(pathview, "textNumber", i);
- QVERIFY(number != 0);
+ QVERIFY(number != nullptr);
QCOMPARE(number->text(), model.number(i));
}
@@ -257,7 +263,7 @@ void tst_QQuickPathView::initialCurrentItem()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QVERIFY(pathview->currentIndex() != -1);
QVERIFY(!window->rootObject()->property("currentItemIsNull").toBool());
}
@@ -268,9 +274,9 @@ void tst_QQuickPathView::pathview2()
QQmlComponent c(&engine, testFileUrl("pathview2.qml"));
QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->path() != 0);
- QVERIFY(obj->delegate() != 0);
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->path() != nullptr);
+ QVERIFY(obj->delegate() != nullptr);
QVERIFY(obj->model() != QVariant());
QCOMPARE(obj->currentIndex(), 0);
QCOMPARE(obj->offset(), 0.);
@@ -288,9 +294,9 @@ void tst_QQuickPathView::pathview3()
QQmlComponent c(&engine, testFileUrl("pathview3.qml"));
QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->path() != 0);
- QVERIFY(obj->delegate() != 0);
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->path() != nullptr);
+ QVERIFY(obj->delegate() != nullptr);
QVERIFY(obj->model() != QVariant());
QCOMPARE(obj->currentIndex(), 7);
QCOMPARE(obj->offset(), 1.0);
@@ -308,9 +314,9 @@ void tst_QQuickPathView::initialCurrentIndex()
QQmlComponent c(&engine, testFileUrl("initialCurrentIndex.qml"));
QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
- QVERIFY(obj != 0);
- QVERIFY(obj->path() != 0);
- QVERIFY(obj->delegate() != 0);
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->path() != nullptr);
+ QVERIFY(obj->delegate() != nullptr);
QVERIFY(obj->model() != QVariant());
QCOMPARE(obj->currentIndex(), 3);
QCOMPARE(obj->offset(), 5.0);
@@ -364,6 +370,10 @@ void tst_QQuickPathView::insertModel_data()
void tst_QQuickPathView::insertModel()
{
+#ifdef Q_OS_MACOS
+ QSKIP("this test currently crashes on MacOS. See QTBUG-68048");
+#endif
+
QFETCH(int, mode);
QFETCH(int, idx);
QFETCH(int, count);
@@ -390,7 +400,7 @@ void tst_QQuickPathView::insertModel()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
@@ -483,7 +493,7 @@ void tst_QQuickPathView::removeModel()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
@@ -576,7 +586,7 @@ void tst_QQuickPathView::moveModel()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
@@ -675,7 +685,7 @@ void tst_QQuickPathView::consecutiveModelChanges()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
pathview->setHighlightRangeMode(mode);
@@ -705,13 +715,13 @@ void tst_QQuickPathView::consecutiveModelChanges()
pathview->setCurrentIndex(changes[i].index);
break;
case ListChange::Polish:
- QQUICK_VERIFY_POLISH(pathview);
+ QQuickTest::qWaitForItemPolished(pathview);
break;
default:
continue;
}
}
- QQUICK_VERIFY_POLISH(pathview);
+ QQuickTest::qWaitForItemPolished(pathview);
QCOMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), count);
QCOMPARE(pathview->count(), count);
@@ -727,7 +737,7 @@ void tst_QQuickPathView::path()
QQmlComponent c(&engine, testFileUrl("pathtest.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->startX(), 120.);
QCOMPARE(obj->startY(), 100.);
QVERIFY(obj->path() != QPainterPath());
@@ -736,28 +746,28 @@ void tst_QQuickPathView::path()
QCOMPARE(list.count(), 5);
QQuickPathAttribute* attr = qobject_cast<QQuickPathAttribute*>(list.at(0));
- QVERIFY(attr != 0);
+ QVERIFY(attr != nullptr);
QCOMPARE(attr->name(), QString("scale"));
QCOMPARE(attr->value(), 1.0);
QQuickPathQuad* quad = qobject_cast<QQuickPathQuad*>(list.at(1));
- QVERIFY(quad != 0);
+ QVERIFY(quad != nullptr);
QCOMPARE(quad->x(), 120.);
QCOMPARE(quad->y(), 25.);
QCOMPARE(quad->controlX(), 260.);
QCOMPARE(quad->controlY(), 75.);
QQuickPathPercent* perc = qobject_cast<QQuickPathPercent*>(list.at(2));
- QVERIFY(perc != 0);
+ QVERIFY(perc != nullptr);
QCOMPARE(perc->value(), 0.3);
QQuickPathLine* line = qobject_cast<QQuickPathLine*>(list.at(3));
- QVERIFY(line != 0);
+ QVERIFY(line != nullptr);
QCOMPARE(line->x(), 120.);
QCOMPARE(line->y(), 100.);
QQuickPathCubic* cubic = qobject_cast<QQuickPathCubic*>(list.at(4));
- QVERIFY(cubic != 0);
+ QVERIFY(cubic != nullptr);
QCOMPARE(cubic->x(), 180.);
QCOMPARE(cubic->y(), 0.);
QCOMPARE(cubic->control1X(), -10.);
@@ -770,6 +780,10 @@ void tst_QQuickPathView::path()
void tst_QQuickPathView::dataModel()
{
+#ifdef Q_OS_MACOS
+ QSKIP("this test currently crashes on MacOS. See QTBUG-68047");
+#endif
+
QScopedPointer<QQuickView> window(createView());
window->show();
@@ -798,7 +812,7 @@ void tst_QQuickPathView::dataModel()
qApp->processEvents();
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
QVERIFY(!testObject->error());
@@ -835,7 +849,7 @@ void tst_QQuickPathView::dataModel()
QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
QQuickRectangle *testItem = findItem<QQuickRectangle>(pathview, "wrapper", 4);
- QVERIFY(testItem != 0);
+ QVERIFY(testItem != nullptr);
testItem = findItem<QQuickRectangle>(pathview, "wrapper", 5);
QVERIFY(!testItem);
@@ -898,7 +912,7 @@ void tst_QQuickPathView::pathMoved()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
QVERIFY(firstItem);
@@ -986,7 +1000,7 @@ void tst_QQuickPathView::setCurrentIndex()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
QVERIFY(firstItem);
@@ -1139,13 +1153,13 @@ void tst_QQuickPathView::resetModel()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QCOMPARE(pathview->count(), model.rowCount());
for (int i = 0; i < model.rowCount(); ++i) {
QQuickText *display = findItem<QQuickText>(pathview, "displayText", i);
- QVERIFY(display != 0);
+ QVERIFY(display != nullptr);
QCOMPARE(display->text(), strings.at(i));
}
@@ -1157,7 +1171,7 @@ void tst_QQuickPathView::resetModel()
for (int i = 0; i < model.rowCount(); ++i) {
QQuickText *display = findItem<QQuickText>(pathview, "displayText", i);
- QVERIFY(display != 0);
+ QVERIFY(display != nullptr);
QCOMPARE(display->text(), strings.at(i));
}
@@ -1358,6 +1372,7 @@ void tst_QQuickPathView::package()
QSKIP("QTBUG-27170 view does not reliably receive polish without a running animation");
#endif
+ QQuickTest::qWaitForItemPolished(pathView);
QQuickItem *item = findItem<QQuickItem>(pathView, "pathItem");
QVERIFY(item);
QVERIFY(item->scale() != 1.0);
@@ -1378,7 +1393,7 @@ void tst_QQuickPathView::emptyModel()
qApp->processEvents();
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QCOMPARE(pathview->offset(), qreal(0.0));
@@ -1392,7 +1407,7 @@ void tst_QQuickPathView::emptyPath()
qApp->processEvents();
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
delete window;
}
@@ -1440,7 +1455,7 @@ void tst_QQuickPathView::visualDataModel()
QQmlComponent c(&engine, testFileUrl("vdm.qml"));
QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->count(), 3);
@@ -1463,7 +1478,7 @@ void tst_QQuickPathView::undefinedPath()
QQmlComponent c(&engine, testFileUrl("undefinedpath.qml"));
QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->count(), 3);
@@ -1481,7 +1496,7 @@ void tst_QQuickPathView::mouseDrag()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QSignalSpy movingSpy(pathview, SIGNAL(movingChanged()));
QSignalSpy moveStartedSpy(pathview, SIGNAL(movementStarted()));
@@ -1492,7 +1507,7 @@ void tst_QQuickPathView::mouseDrag()
int current = pathview->currentIndex();
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(10,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(10,100));
QTest::qWait(100);
{
@@ -1529,7 +1544,7 @@ void tst_QQuickPathView::mouseDrag()
QVERIFY(pathview->currentIndex() != current);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(40,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(40,100));
QVERIFY(!pathview->isDragging());
QCOMPARE(draggingSpy.count(), 2);
QCOMPARE(dragStartedSpy.count(), 1);
@@ -1552,7 +1567,7 @@ void tst_QQuickPathView::nestedMouseAreaDrag()
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
// Dragging the child mouse area should move it and not animate the PathView
flick(window.data(), QPoint(200,200), QPoint(400,200), 200);
@@ -1575,7 +1590,7 @@ void tst_QQuickPathView::treeModel()
window->setSource(testFileUrl("treemodel.qml"));
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QCOMPARE(pathview->count(), 3);
QQuickText *item = findItem<QQuickText>(pathview, "wrapper", 0);
@@ -1601,7 +1616,7 @@ void tst_QQuickPathView::changePreferredHighlight()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
int current = pathview->currentIndex();
QCOMPARE(current, 0);
@@ -1654,7 +1669,7 @@ void tst_QQuickPathView::currentOffsetOnInsertion()
qApp->processEvents();
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
pathview->setPreferredHighlightBegin(0.5);
pathview->setPreferredHighlightEnd(0.5);
@@ -1665,7 +1680,7 @@ void tst_QQuickPathView::currentOffsetOnInsertion()
QCOMPARE(pathview->count(), model.count());
- QQuickRectangle *item = 0;
+ QQuickRectangle *item = nullptr;
QTRY_VERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 0));
QQuickPath *path = qobject_cast<QQuickPath*>(pathview->path());
@@ -1732,7 +1747,7 @@ void tst_QQuickPathView::asynchronous()
QQuickItem *rootObject = qobject_cast<QQuickItem*>(window->rootObject());
QVERIFY(rootObject);
- QQuickPathView *pathview = 0;
+ QQuickPathView *pathview = nullptr;
while (!pathview) {
bool b = false;
controller.incubateWhile(&b);
@@ -1741,8 +1756,8 @@ void tst_QQuickPathView::asynchronous()
// items will be created one at a time
for (int i = 0; i < 5; ++i) {
- QVERIFY(findItem<QQuickItem>(pathview, "wrapper", i) == 0);
- QQuickItem *item = 0;
+ QVERIFY(findItem<QQuickItem>(pathview, "wrapper", i) == nullptr);
+ QQuickItem *item = nullptr;
while (!item) {
bool b = false;
controller.incubateWhile(&b);
@@ -1804,14 +1819,14 @@ void tst_QQuickPathView::cancelDrag()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QSignalSpy draggingSpy(pathview, SIGNAL(draggingChanged()));
QSignalSpy dragStartedSpy(pathview, SIGNAL(dragStarted()));
QSignalSpy dragEndedSpy(pathview, SIGNAL(dragEnded()));
// drag between snap points
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(10,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(10,100));
QTest::qWait(100);
QTest::mouseMove(window.data(), QPoint(80, 100));
QTest::mouseMove(window.data(), QPoint(130, 100));
@@ -1835,7 +1850,7 @@ void tst_QQuickPathView::cancelDrag()
QCOMPARE(dragStartedSpy.count(), 1);
QCOMPARE(dragEndedSpy.count(), 1);
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(40,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(40,100));
}
@@ -1850,7 +1865,7 @@ void tst_QQuickPathView::maximumFlickVelocity()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
pathview->setMaximumFlickVelocity(700);
flick(window.data(), QPoint(200,10), QPoint(10,10), 180);
@@ -1897,7 +1912,7 @@ void tst_QQuickPathView::snapToItem()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = window->rootObject()->findChild<QQuickPathView*>("view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
window->rootObject()->setProperty("enforceRange", enforceRange);
QTRY_VERIFY(!pathview->isMoving()); // ensure stable
@@ -1941,7 +1956,7 @@ void tst_QQuickPathView::snapOneItem()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = window->rootObject()->findChild<QQuickPathView*>("view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
window->rootObject()->setProperty("enforceRange", enforceRange);
@@ -1994,7 +2009,7 @@ void tst_QQuickPathView::positionViewAtIndex()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
window->rootObject()->setProperty("enforceRange", enforceRange);
if (pathItemCount == -1)
@@ -2057,9 +2072,9 @@ void tst_QQuickPathView::indexAt_itemAt()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
if (index >= 0) {
item = findItem<QQuickItem>(pathview, "wrapper", index);
QVERIFY(item);
@@ -2091,7 +2106,7 @@ void tst_QQuickPathView::cacheItemCount()
qApp->processEvents();
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QMetaObject::invokeMethod(pathview, "addColor", Q_ARG(QVariant, QString("orange")));
QMetaObject::invokeMethod(pathview, "addColor", Q_ARG(QVariant, QString("lightsteelblue")));
@@ -2117,8 +2132,8 @@ void tst_QQuickPathView::cacheItemCount()
int i = 0;
while (cached[i] >= 0) {
// items will be created one at a time
- QVERIFY(findItem<QQuickItem>(pathview, "wrapper", cached[i]) == 0);
- QQuickItem *item = 0;
+ QVERIFY(findItem<QQuickItem>(pathview, "wrapper", cached[i]) == nullptr);
+ QQuickItem *item = nullptr;
while (!item) {
bool b = false;
controller.incubateWhile(&b);
@@ -2145,8 +2160,8 @@ void tst_QQuickPathView::cacheItemCount()
QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 11));
// one item prepended async.
- QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 5) == 0);
- QQuickItem *item = 0;
+ QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 5) == nullptr);
+ QQuickItem *item = nullptr;
while (!item) {
bool b = false;
controller.incubateWhile(&b);
@@ -2182,7 +2197,7 @@ void tst_QQuickPathView::changePathDuringRefill()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathView = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathView != 0);
+ QVERIFY(pathView != nullptr);
testCurrentIndexChange(pathView, QStringList() << "delegateC" << "delegateA" << "delegateB");
@@ -2210,10 +2225,10 @@ void tst_QQuickPathView::nestedinFlickable()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "pathView");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QSignalSpy movingSpy(pathview, SIGNAL(movingChanged()));
QSignalSpy moveStartedSpy(pathview, SIGNAL(movementStarted()));
@@ -2225,7 +2240,7 @@ void tst_QQuickPathView::nestedinFlickable()
int waitInterval = 5;
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(23,218));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(23,218));
QTest::mouseMove(window.data(), QPoint(25,218), waitInterval);
QTest::mouseMove(window.data(), QPoint(26,218), waitInterval);
@@ -2244,7 +2259,7 @@ void tst_QQuickPathView::nestedinFlickable()
QCOMPARE(fflickEndedSpy.count(), 0);
// no further moves after the initial move beyond threshold
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(73,219));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(73,219));
QTRY_COMPARE(movingSpy.count(), 2);
QTRY_COMPARE(moveEndedSpy.count(), 1);
QCOMPARE(moveStartedSpy.count(), 1);
@@ -2252,6 +2267,59 @@ void tst_QQuickPathView::nestedinFlickable()
QCOMPARE(fflickingSpy.count(), 0);
QCOMPARE(fflickStartedSpy.count(), 0);
QCOMPARE(fflickEndedSpy.count(), 0);
+
+ // now test that two quick flicks are both handled by the pathview
+ movingSpy.clear();
+ moveStartedSpy.clear();
+ moveEndedSpy.clear();
+ fflickingSpy.clear();
+ fflickStartedSpy.clear();
+ fflickEndedSpy.clear();
+ int shortInterval = 2;
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(23,216));
+ QTest::mouseMove(window.data(), QPoint(48,216), shortInterval);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(73,217));
+ QVERIFY(pathview->isMoving());
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(21,216));
+ QTest::mouseMove(window.data(), QPoint(46,216), shortInterval);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(71,217));
+ QVERIFY(pathview->isMoving());
+ // moveEndedSpy.count() and moveStartedSpy.count() should be exactly 1
+ // but in CI we sometimes see a scheduling issue being hit which
+ // causes the main thread to be stalled while the animation thread
+ // continues, allowing the animation timer to finish after the first
+ // call to QVERIFY(pathview->isMoving()) in the code above, prior to
+ // the detected beginning of the second flick, which can cause both of
+ // those signal counts to be 2 rather than 1.
+ // Note that this is not a true problem (this scheduling quirk just
+ // means that the unit test is not testing the enforced behavior
+ // as strictly as it would otherwise); it is only a bug if it results
+ // in the Flickable handling one or more of the flicks, and that
+ // is unconditionally tested below.
+ // To avoid false positive test failure in the scheduling quirk case
+ // we allow the multiple signal count case, rather than simply:
+ // QTRY_COMPARE(moveEndedSpy.count(), 1);
+ // QCOMPARE(moveStartedSpy.count(), 1);
+ QTRY_VERIFY(moveEndedSpy.count() > 0);
+ qCDebug(lcTests) << "After receiving moveEnded signal:"
+ << "moveEndedSpy.count():" << moveEndedSpy.count()
+ << "moveStartedSpy.count():" << moveStartedSpy.count()
+ << "fflickingSpy.count():" << fflickingSpy.count()
+ << "fflickStartedSpy.count():" << fflickStartedSpy.count()
+ << "fflickEndedSpy.count():" << fflickEndedSpy.count();
+ QTRY_COMPARE(moveStartedSpy.count(), moveEndedSpy.count());
+ qCDebug(lcTests) << "After receiving matched moveEnded signal(s):"
+ << "moveEndedSpy.count():" << moveEndedSpy.count()
+ << "moveStartedSpy.count():" << moveStartedSpy.count()
+ << "fflickingSpy.count():" << fflickingSpy.count()
+ << "fflickStartedSpy.count():" << fflickStartedSpy.count()
+ << "fflickEndedSpy.count():" << fflickEndedSpy.count();
+ QVERIFY(moveStartedSpy.count() <= 2);
+ // Flickable should not handle this
+ QCOMPARE(fflickingSpy.count(), 0);
+ QCOMPARE(fflickStartedSpy.count(), 0);
+ QCOMPARE(fflickEndedSpy.count(), 0);
+
}
void tst_QQuickPathView::flickableDelegate()
@@ -2265,10 +2333,10 @@ void tst_QQuickPathView::flickableDelegate()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(pathview->currentItem());
- QVERIFY(flickable != 0);
+ QVERIFY(flickable != nullptr);
QSignalSpy movingSpy(pathview, SIGNAL(movingChanged()));
QSignalSpy moveStartedSpy(pathview, SIGNAL(movementStarted()));
@@ -2280,7 +2348,7 @@ void tst_QQuickPathView::flickableDelegate()
int waitInterval = 5;
- QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(23,100));
+ QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(23,100));
QTest::mouseMove(window.data(), QPoint(25,100), waitInterval);
QTest::mouseMove(window.data(), QPoint(26,100), waitInterval);
@@ -2299,7 +2367,7 @@ void tst_QQuickPathView::flickableDelegate()
QCOMPARE(fflickEndedSpy.count(), 0);
// no further moves after the initial move beyond threshold
- QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(53,100));
+ QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(53,100));
QTRY_COMPARE(fflickingSpy.count(), 2);
QTRY_COMPARE(fflickStartedSpy.count(), 1);
QCOMPARE(fflickEndedSpy.count(), 1);
@@ -2349,7 +2417,7 @@ void tst_QQuickPathView::qtbug37815()
QTest::qWait(1000);
QQuickPathView *pathView = findItem<QQuickPathView>(window->rootObject(), "pathView");
- QVERIFY(pathView != Q_NULLPTR);
+ QVERIFY(pathView != nullptr);
const int pathItemCount = pathView->pathItemCount();
const int cacheItemCount = pathView->cacheItemCount();
@@ -2377,7 +2445,7 @@ void tst_QQuickPathView::qtbug42716()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathView = findItem<QQuickPathView>(window->rootObject(), "pathView");
- QVERIFY(pathView != 0);
+ QVERIFY(pathView != nullptr);
int order1[] = {5,6,7,0,1,2,3};
int missing1 = 4;
@@ -2419,7 +2487,7 @@ void tst_QQuickPathView::qtbug53464()
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickPathView *pathView = findItem<QQuickPathView>(window->rootObject(), "pathView");
- QVERIFY(pathView != Q_NULLPTR);
+ QVERIFY(pathView != nullptr);
const int currentIndex = pathView->currentIndex();
QCOMPARE(currentIndex, 8);
@@ -2460,9 +2528,11 @@ static void verify_offsets(QQuickPathView *pathview, int toidx, qreal fromoffset
QTest::qWait(100);
first = pathview->offset();
while (1) {
+ if (first == 0)
+ first = pathview->offset();
QTest::qWait(10); // highlightMoveDuration: 1000
second = pathview->offset();
- if (!started && second != first) { // animation started
+ if (!started && first != 0 && second != first) { // animation started
started = true;
break;
}
@@ -2496,7 +2566,7 @@ void tst_QQuickPathView::movementDirection()
QCOMPARE(window.data(), qGuiApp->focusWindow());
QQuickPathView *pathview = window->rootObject()->findChild<QQuickPathView*>("view");
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QVERIFY(pathview->offset() == 0.0);
QVERIFY(pathview->currentIndex() == 0);
pathview->setMovementDirection(movementdirection);
@@ -2512,12 +2582,59 @@ void tst_QQuickPathView::removePath()
window->show();
QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
- QVERIFY(pathview != 0);
+ QVERIFY(pathview != nullptr);
QVERIFY(QMetaObject::invokeMethod(pathview, "removePath"));
QVERIFY(QMetaObject::invokeMethod(pathview, "setPath"));
}
+/*
+ Tests that moving items in an ObjectModel and then deleting the view
+ doesn't cause heap-use-after-free when run through ASAN.
+
+ The test case is based on a Qt Quick Controls 2 test where the issue was
+ discovered.
+*/
+void tst_QQuickPathView::objectModelMove()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("objectModelMove.qml"));
+ window->show();
+
+ // Create the view.
+ QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "newView"));
+ QPointer<QQuickPathView> pathView = window->rootObject()->property("pathViewItem").value<QQuickPathView*>();
+ QVERIFY(pathView);
+ QCOMPARE(pathView->count(), 3);
+ pathView->highlightItem()->setObjectName("highlight");
+
+ // Move an item from index 0 to 1.
+ QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "move"));
+ QCOMPARE(pathView->count(), 3);
+
+ // Keep track of the amount of listeners
+ QVector<QString> itemObjectNames;
+ itemObjectNames << QLatin1String("red") << QLatin1String("green") << QLatin1String("blue");
+ QVector<QQuickItem*> childItems;
+ for (const QString itemObjectName : qAsConst(itemObjectNames)) {
+ QQuickItem *childItem = findItem<QQuickItem>(pathView, itemObjectName);
+ QVERIFY(childItem);
+ childItems.append(childItem);
+ }
+
+ // Destroy the view (via destroy()).
+ QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "destroyView"));
+ // Ensure that the view has been destroyed. This check is also necessary in order for
+ // ASAN to complain (it will complain after the test function has finished).
+ QTRY_VERIFY(pathView.isNull());
+ // By this point, all of its cached items should have been released,
+ // which means none of the items should have any listeners.
+ for (const auto childItem : qAsConst(childItems)) {
+ const QQuickItemPrivate *childItemPrivate = QQuickItemPrivate::get(childItem);
+ QCOMPARE(childItemPrivate->changeListeners.size(), 0);
+ }
+}
+
QTEST_MAIN(tst_QQuickPathView)
#include "tst_qquickpathview.moc"
diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
index c1a51fd659..5b7108d96b 100644
--- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
+++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -41,7 +41,7 @@ class tst_QQuickPinchArea: public QQmlDataTest
{
Q_OBJECT
public:
- tst_QQuickPinchArea() : device(0) { }
+ tst_QQuickPinchArea() { }
private slots:
void initTestCase();
void cleanupTestCase();
@@ -55,7 +55,7 @@ private slots:
private:
QQuickView *createView();
- QTouchDevice *device;
+ QTouchDevice *device = nullptr;
};
void tst_QQuickPinchArea::initTestCase()
{
@@ -76,19 +76,19 @@ void tst_QQuickPinchArea::pinchProperties()
QScopedPointer<QQuickView> window(createView());
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
+ QVERIFY(pinchArea != nullptr);
+ QVERIFY(pinch != nullptr);
// target
QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QCOMPARE(blackRect, pinch->target());
QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
- QVERIFY(rootItem != 0);
+ QVERIFY(rootItem != nullptr);
QSignalSpy targetSpy(pinch, SIGNAL(targetChanged()));
pinch->setTarget(rootItem);
QCOMPARE(targetSpy.count(),1);
@@ -201,20 +201,20 @@ void tst_QQuickPinchArea::scale()
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
qApp->processEvents();
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
+ QVERIFY(pinchArea != nullptr);
+ QVERIFY(pinch != nullptr);
QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
// target
QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QPoint p1(80, 80);
QPoint p2(100, 100);
@@ -268,20 +268,20 @@ void tst_QQuickPinchArea::pan()
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
qApp->processEvents();
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
+ QVERIFY(pinchArea != nullptr);
+ QVERIFY(pinch != nullptr);
QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
// target
QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QPoint p1(80, 80);
QPoint p2(100, 100);
@@ -374,23 +374,23 @@ void tst_QQuickPinchArea::retouch()
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
qApp->processEvents();
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
+ QVERIFY(pinchArea != nullptr);
+ QVERIFY(pinch != nullptr);
QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QSignalSpy startedSpy(pinchArea, SIGNAL(pinchStarted(QQuickPinchEvent*)));
QSignalSpy finishedSpy(pinchArea, SIGNAL(pinchFinished(QQuickPinchEvent*)));
// target
QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QPoint p1(80, 80);
QPoint p2(100, 100);
@@ -465,20 +465,20 @@ void tst_QQuickPinchArea::cancel()
window->setSource(testFileUrl("pinchproperties.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
qApp->processEvents();
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
QQuickPinch *pinch = pinchArea->pinch();
- QVERIFY(pinchArea != 0);
- QVERIFY(pinch != 0);
+ QVERIFY(pinchArea != nullptr);
+ QVERIFY(pinch != nullptr);
QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
// target
QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
- QVERIFY(blackRect != 0);
+ QVERIFY(blackRect != nullptr);
QPoint p1(80, 80);
QPoint p2(100, 100);
@@ -558,11 +558,11 @@ void tst_QQuickPinchArea::transformedPinchArea()
view->setSource(testFileUrl("transformedPinchArea.qml"));
view->show();
QVERIFY(QTest::qWaitForWindowExposed(view));
- QVERIFY(view->rootObject() != 0);
+ QVERIFY(view->rootObject() != nullptr);
qApp->processEvents();
QQuickPinchArea *pinchArea = view->rootObject()->findChild<QQuickPinchArea*>("pinchArea");
- QVERIFY(pinchArea != 0);
+ QVERIFY(pinchArea != nullptr);
const int threshold = qApp->styleHints()->startDragDistance();
@@ -588,7 +588,7 @@ void tst_QQuickPinchArea::transformedPinchArea()
QQuickView *tst_QQuickPinchArea::createView()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setGeometry(0,0,240,320);
return window;
diff --git a/tests/auto/quick/qquickpixmapcache/qquickpixmapcache.pro b/tests/auto/quick/qquickpixmapcache/qquickpixmapcache.pro
index 185eb2c213..52b798e829 100644
--- a/tests/auto/quick/qquickpixmapcache/qquickpixmapcache.pro
+++ b/tests/auto/quick/qquickpixmapcache/qquickpixmapcache.pro
@@ -5,7 +5,6 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qquickpixmapcache.cpp \
../../shared/testhttpserver.cpp
HEADERS += ../../shared/testhttpserver.h
-INCLUDEPATH += ../../shared/
include (../../shared/util.pri)
diff --git a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
index e854a109a1..bffaaf7c6e 100644
--- a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
+++ b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
@@ -431,7 +431,7 @@ void tst_qquickpixmapcache::uncached()
QUrl url("image://mypixmaps/mypix");
{
QQuickPixmap p;
- p.load(&engine, url, 0);
+ p.load(&engine, url, nullptr);
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(255, 0, 0));
}
@@ -440,7 +440,7 @@ void tst_qquickpixmapcache::uncached()
MyPixmapProvider::fillColor = qRgb(0, 255, 0);
{
QQuickPixmap p;
- p.load(&engine, url, 0);
+ p.load(&engine, url, nullptr);
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(0, 255, 0));
}
@@ -458,7 +458,7 @@ void tst_qquickpixmapcache::uncached()
MyPixmapProvider::fillColor = qRgb(255, 0, 255);
{
QQuickPixmap p;
- p.load(&engine, url, 0);
+ p.load(&engine, url, nullptr);
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(255, 0, 255));
}
diff --git a/tests/auto/quick/qquickpositioners/qquickpositioners.pro b/tests/auto/quick/qquickpositioners/qquickpositioners.pro
index 6e85ba9db8..d1547df189 100644
--- a/tests/auto/quick/qquickpositioners/qquickpositioners.pro
+++ b/tests/auto/quick/qquickpositioners/qquickpositioners.pro
@@ -9,4 +9,4 @@ macx:CONFIG -= app_bundle
TESTDATA = data/*
-QT += testlib
+QT += testlib qmltest
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index 1b3939401a..80be25d1b0 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -31,6 +31,7 @@
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/private/qquickpositioners_p.h>
#include <QtQuick/private/qquicktransition_p.h>
+#include <QtQuickTest/QtQuickTest>
#include <private/qquickitem_p.h>
#include <qqmlexpression.h>
#include "../shared/viewtestutil.h"
@@ -40,6 +41,8 @@
using namespace QQuickViewTestUtil;
using namespace QQuickVisualTestUtil;
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
class tst_qquickpositioners : public QQmlDataTest
{
Q_OBJECT
@@ -313,13 +316,13 @@ void tst_qquickpositioners::test_horizontal()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -357,13 +360,13 @@ void tst_qquickpositioners::test_horizontal_padding()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -377,7 +380,7 @@ void tst_qquickpositioners::test_horizontal_padding()
QCOMPARE(row->height(), 50.0);
QQuickRow *obj = qobject_cast<QQuickRow*>(row);
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(row->property("padding").toDouble(), 0.0);
QCOMPARE(row->property("topPadding").toDouble(), 0.0);
@@ -519,13 +522,13 @@ void tst_qquickpositioners::test_horizontal_rtl()
window->rootObject()->setProperty("testRightToLeft", true);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 60.0);
QCOMPARE(one->y(), 0.0);
@@ -598,13 +601,13 @@ void tst_qquickpositioners::test_horizontal_spacing()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -642,13 +645,13 @@ void tst_qquickpositioners::test_horizontal_spacing_rightToLeft()
window->rootObject()->setProperty("testRightToLeft", true);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 80.0);
QCOMPARE(one->y(), 0.0);
@@ -686,13 +689,13 @@ void tst_qquickpositioners::test_horizontal_animated()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
//Note that they animate in
QCOMPARE(one->x(), -100.0);
@@ -739,13 +742,13 @@ void tst_qquickpositioners::test_horizontal_animated_padding()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
//Note that they animate in
QCOMPARE(one->x(), -100.0);
@@ -803,13 +806,13 @@ void tst_qquickpositioners::test_horizontal_animated_rightToLeft()
window->rootObject()->setProperty("testRightToLeft", true);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
//Note that they animate in
QCOMPARE(one->x(), -100.0);
@@ -858,13 +861,13 @@ void tst_qquickpositioners::test_horizontal_animated_rightToLeft_padding()
window->rootObject()->setProperty("testRightToLeft", true);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
//Note that they animate in
QCOMPARE(one->x(), -100.0);
@@ -922,13 +925,13 @@ void tst_qquickpositioners::test_horizontal_animated_disabled()
QScopedPointer<QQuickView> window(createView(testFile("horizontal-animated-disabled.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickItem *row = window->rootObject()->findChild<QQuickItem*>("row");
QVERIFY(row);
@@ -970,13 +973,13 @@ void tst_qquickpositioners::test_horizontal_animated_disabled_padding()
QScopedPointer<QQuickView> window(createView(testFile("horizontal-animated-disabled.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickItem *row = window->rootObject()->findChild<QQuickItem*>("row");
QVERIFY(row);
@@ -1037,7 +1040,7 @@ void tst_qquickpositioners::populateTransitions(const QString &positionerObjectN
QQuickItem *positioner = window->rootObject()->findChild<QQuickItem*>(positionerObjectName);
QVERIFY(positioner);
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
qApp->processEvents();
if (!dynamicallyPopulate && usePopulateTransition) {
@@ -1060,7 +1063,7 @@ void tst_qquickpositioners::populateTransitions(const QString &positionerObjectN
QTRY_COMPARE(window->rootObject()->property("populateTransitionsDone").toInt(), 0);
QTRY_COMPARE(window->rootObject()->property("addTransitionsDone").toInt(), model.count());
} else {
- QTRY_COMPARE(QQuickItemPrivate::get(positioner)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(positioner));
QTRY_COMPARE(window->rootObject()->property("populateTransitionsDone").toInt(), 0);
QTRY_COMPARE(window->rootObject()->property("addTransitionsDone").toInt(), 0);
}
@@ -1120,13 +1123,13 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
ctxt->setContextProperty("testedPositioner", QString());
window->setSource(testFileUrl(qmlFile));
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
qApp->processEvents();
QQuickItem *positioner = window->rootObject()->findChild<QQuickItem*>(positionerObjectName);
QVERIFY(positioner);
positioner->findChild<QQuickItem*>("repeater")->setProperty("model", QVariant::fromValue(&model));
- QTRY_COMPARE(QQuickItemPrivate::get(positioner)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(positioner));
for (int i = 0; i < initialItemCount; i++)
model.addItem("Original item" + QString::number(i), "");
@@ -1243,7 +1246,7 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
ctxt->setContextProperty("testedPositioner", QString());
window->setSource(testFileUrl(qmlFile));
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
qApp->processEvents();
QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
@@ -1251,7 +1254,7 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
QQuickItem *positioner = window->rootObject()->findChild<QQuickItem*>(positionerObjectName);
QVERIFY(positioner);
positioner->findChild<QQuickItem*>("repeater")->setProperty("model", QVariant::fromValue(&model));
- QTRY_COMPARE(QQuickItemPrivate::get(positioner)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(positioner));
switch (change.type) {
case ListChange::Removed:
@@ -1260,7 +1263,7 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
break;
case ListChange::Moved:
model.moveItems(change.index, change.to, change.count);
- QTRY_COMPARE(QQuickItemPrivate::get(positioner)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(positioner));
break;
case ListChange::Inserted:
case ListChange::SetCurrent:
@@ -1390,7 +1393,7 @@ void tst_qquickpositioners::checkItemPositions(QQuickItem *positioner, QaimModel
QVERIFY2(false, "Unknown positioner type");
}
QQuickText *name = findItem<QQuickText>(positioner, "name", i);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QTRY_COMPARE(name->text(), model->name(i));
padding += i * incrementalSize;
@@ -1403,13 +1406,13 @@ void tst_qquickpositioners::test_vertical()
QScopedPointer<QQuickView> window(createView(testFile("vertical.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -1446,13 +1449,13 @@ void tst_qquickpositioners::test_vertical_padding()
QScopedPointer<QQuickView> window(createView(testFile("vertical.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -1467,7 +1470,7 @@ void tst_qquickpositioners::test_vertical_padding()
QCOMPARE(column->width(), 50.0);
QQuickColumn *obj = qobject_cast<QQuickColumn*>(column);
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(column->property("padding").toDouble(), 0.0);
QCOMPARE(column->property("topPadding").toDouble(), 0.0);
@@ -1607,13 +1610,13 @@ void tst_qquickpositioners::test_vertical_spacing()
QScopedPointer<QQuickView> window(createView(testFile("vertical-spacing.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -1650,15 +1653,15 @@ void tst_qquickpositioners::test_vertical_animated()
//Note that they animate in
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QCOMPARE(one->y(), -100.0);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QCOMPARE(two->y(), -100.0);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(three->y(), -100.0);
QVERIFY(QTest::qWaitForWindowExposed(window.data())); //It may not relayout until the next frame, so it needs to be drawn
@@ -1699,15 +1702,15 @@ void tst_qquickpositioners::test_vertical_animated_padding()
//Note that they animate in
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QCOMPARE(one->y(), -100.0);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QCOMPARE(two->y(), -100.0);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(three->y(), -100.0);
QVERIFY(QTest::qWaitForWindowExposed(window.data())); //It may not relayout until the next frame, so it needs to be drawn
@@ -1758,15 +1761,15 @@ void tst_qquickpositioners::test_grid()
QScopedPointer<QQuickView> window(createView(testFile("gridtest.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -1811,15 +1814,15 @@ void tst_qquickpositioners::test_grid_padding()
QScopedPointer<QQuickView> window(createView(testFile("gridtest.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -1999,15 +2002,15 @@ void tst_qquickpositioners::test_grid_topToBottom()
QScopedPointer<QQuickView> window(createView(testFile("grid-toptobottom.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -2054,15 +2057,15 @@ void tst_qquickpositioners::test_grid_rightToLeft()
window->rootObject()->setProperty("testRightToLeft", true);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 50.0);
QCOMPARE(one->y(), 0.0);
@@ -2154,15 +2157,15 @@ void tst_qquickpositioners::test_grid_spacing()
QScopedPointer<QQuickView> window(createView(testFile("grid-spacing.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -2206,15 +2209,15 @@ void tst_qquickpositioners::test_grid_row_column_spacing()
QScopedPointer<QQuickView> window(createView(testFile("grid-row-column-spacing.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -2261,27 +2264,27 @@ void tst_qquickpositioners::test_grid_animated()
//Note that all animate in
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QCOMPARE(one->x(), -100.0);
QCOMPARE(one->y(), -100.0);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QCOMPARE(two->x(), -100.0);
QCOMPARE(two->y(), -100.0);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(three->x(), -100.0);
QCOMPARE(three->y(), -100.0);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QCOMPARE(four->x(), -100.0);
QCOMPARE(four->y(), -100.0);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(five->x(), -100.0);
QCOMPARE(five->y(), -100.0);
@@ -2345,27 +2348,27 @@ void tst_qquickpositioners::test_grid_animated_padding()
//Note that all animate in
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QCOMPARE(one->x(), -100.0);
QCOMPARE(one->y(), -100.0);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QCOMPARE(two->x(), -100.0);
QCOMPARE(two->y(), -100.0);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(three->x(), -100.0);
QCOMPARE(three->y(), -100.0);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QCOMPARE(four->x(), -100.0);
QCOMPARE(four->y(), -100.0);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(five->x(), -100.0);
QCOMPARE(five->y(), -100.0);
@@ -2439,27 +2442,27 @@ void tst_qquickpositioners::test_grid_animated_rightToLeft()
//Note that all animate in
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QCOMPARE(one->x(), -100.0);
QCOMPARE(one->y(), -100.0);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QCOMPARE(two->x(), -100.0);
QCOMPARE(two->y(), -100.0);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(three->x(), -100.0);
QCOMPARE(three->y(), -100.0);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QCOMPARE(four->x(), -100.0);
QCOMPARE(four->y(), -100.0);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(five->x(), -100.0);
QCOMPARE(five->y(), -100.0);
@@ -2523,27 +2526,27 @@ void tst_qquickpositioners::test_grid_animated_rightToLeft_padding()
//Note that all animate in
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QCOMPARE(one->x(), -100.0);
QCOMPARE(one->y(), -100.0);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QCOMPARE(two->x(), -100.0);
QCOMPARE(two->y(), -100.0);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(three->x(), -100.0);
QCOMPARE(three->y(), -100.0);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QCOMPARE(four->x(), -100.0);
QCOMPARE(four->y(), -100.0);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(five->x(), -100.0);
QCOMPARE(five->y(), -100.0);
@@ -2614,15 +2617,15 @@ void tst_qquickpositioners::test_grid_zero_columns()
QScopedPointer<QQuickView> window(createView(testFile("gridzerocolumns.qml")));
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -2668,15 +2671,15 @@ void tst_qquickpositioners::test_grid_H_alignment()
window->rootObject()->setProperty("testHAlignment", QQuickGrid::AlignHCenter);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -2747,15 +2750,15 @@ void tst_qquickpositioners::test_grid_H_alignment_padding()
window->rootObject()->setProperty("testHAlignment", QQuickGrid::AlignHCenter);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -2836,15 +2839,15 @@ void tst_qquickpositioners::test_grid_V_alignment()
window->rootObject()->setProperty("testVAlignment", QQuickGrid::AlignVCenter);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -2879,15 +2882,15 @@ void tst_qquickpositioners::test_grid_V_alignment_padding()
window->rootObject()->setProperty("testVAlignment", QQuickGrid::AlignVCenter);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QQuickItem *grid = window->rootObject()->findChild<QQuickItem*>("grid");
QCOMPARE(grid->width(), 100.0);
@@ -2934,7 +2937,7 @@ void tst_qquickpositioners::test_propertychanges()
QScopedPointer<QQuickView> window(createView(testFile("propertychangestest.qml")));
QQuickGrid *grid = qobject_cast<QQuickGrid*>(window->rootObject());
- QVERIFY(grid != 0);
+ QVERIFY(grid != nullptr);
QQuickTransition *rowTransition = window->rootObject()->findChild<QQuickTransition*>("rowTransition");
QQuickTransition *columnTransition = window->rootObject()->findChild<QQuickTransition*>("columnTransition");
@@ -2963,8 +2966,8 @@ void tst_qquickpositioners::test_propertychanges()
QCOMPARE(addSpy.count(),1);
QCOMPARE(moveSpy.count(),1);
- grid->setAdd(0);
- grid->setMove(0);
+ grid->setAdd(nullptr);
+ grid->setMove(nullptr);
QCOMPARE(addSpy.count(),2);
QCOMPARE(moveSpy.count(),2);
@@ -2992,13 +2995,13 @@ void tst_qquickpositioners::test_repeater()
QScopedPointer<QQuickView> window(createView(testFile("repeatertest.qml")));
QQuickRectangle *one = findItem<QQuickRectangle>(window->contentItem(), "one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = findItem<QQuickRectangle>(window->contentItem(), "two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = findItem<QQuickRectangle>(window->contentItem(), "three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -3014,13 +3017,13 @@ void tst_qquickpositioners::test_repeater_padding()
QScopedPointer<QQuickView> window(createView(testFile("repeatertest-padding.qml")));
QQuickRectangle *one = findItem<QQuickRectangle>(window->contentItem(), "one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = findItem<QQuickRectangle>(window->contentItem(), "two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = findItem<QQuickRectangle>(window->contentItem(), "three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QCOMPARE(one->x(), 3.0);
QCOMPARE(one->y(), 2.0);
@@ -3038,15 +3041,15 @@ void tst_qquickpositioners::test_flow()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -3093,15 +3096,15 @@ void tst_qquickpositioners::test_flow_padding()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -3120,7 +3123,7 @@ void tst_qquickpositioners::test_flow_padding()
QCOMPARE(flow->height(), 120.0);
QQuickFlow *obj = qobject_cast<QQuickFlow*>(flow);
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(flow->property("padding").toDouble(), 0.0);
QCOMPARE(flow->property("topPadding").toDouble(), 0.0);
@@ -3286,15 +3289,15 @@ void tst_qquickpositioners::test_flow_rightToLeft()
window->rootObject()->setProperty("testRightToLeft", true);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 40.0);
QCOMPARE(one->y(), 0.0);
@@ -3341,15 +3344,15 @@ void tst_qquickpositioners::test_flow_topToBottom()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -3393,15 +3396,15 @@ void tst_qquickpositioners::test_flow_topToBottom_padding()
window->rootObject()->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 0.0);
QCOMPARE(one->y(), 0.0);
@@ -3469,15 +3472,15 @@ void tst_qquickpositioners::test_flow_resize()
root->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QTRY_COMPARE(one->x(), 0.0);
QTRY_COMPARE(one->y(), 0.0);
@@ -3502,15 +3505,15 @@ void tst_qquickpositioners::test_flow_resize_padding()
root->setProperty("testRightToLeft", false);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QVERIFY(one != 0);
+ QVERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QTRY_COMPARE(one->x(), 3.0);
QTRY_COMPARE(one->y(), 2.0);
@@ -3535,15 +3538,15 @@ void tst_qquickpositioners::test_flow_resize_rightToLeft()
root->setProperty("testRightToLeft", true);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QTRY_VERIFY(one != 0);
+ QTRY_VERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 75.0);
QCOMPARE(one->y(), 0.0);
@@ -3568,15 +3571,15 @@ void tst_qquickpositioners::test_flow_resize_rightToLeft_padding()
root->setProperty("testRightToLeft", true);
QQuickRectangle *one = window->rootObject()->findChild<QQuickRectangle*>("one");
- QTRY_VERIFY(one != 0);
+ QTRY_VERIFY(one != nullptr);
QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
- QVERIFY(two != 0);
+ QVERIFY(two != nullptr);
QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
- QVERIFY(three != 0);
+ QVERIFY(three != nullptr);
QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
- QVERIFY(four != 0);
+ QVERIFY(four != nullptr);
QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("five");
- QVERIFY(five != 0);
+ QVERIFY(five != nullptr);
QCOMPARE(one->x(), 71.0);
QCOMPARE(one->y(), 2.0);
@@ -3594,10 +3597,10 @@ void tst_qquickpositioners::test_flow_resize_rightToLeft_padding()
void tst_qquickpositioners::test_flow_implicit_resize()
{
QScopedPointer<QQuickView> window(createView(testFile("flow-testimplicitsize.qml")));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlow *flow = window->rootObject()->findChild<QQuickFlow*>("flow");
- QVERIFY(flow != 0);
+ QVERIFY(flow != nullptr);
QCOMPARE(flow->width(), 100.0);
QCOMPARE(flow->height(), 120.0);
@@ -3622,10 +3625,10 @@ void tst_qquickpositioners::test_flow_implicit_resize()
void tst_qquickpositioners::test_flow_implicit_resize_padding()
{
QScopedPointer<QQuickView> window(createView(testFile("flow-testimplicitsize.qml")));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlow *flow = window->rootObject()->findChild<QQuickFlow*>("flow");
- QVERIFY(flow != 0);
+ QVERIFY(flow != nullptr);
QCOMPARE(flow->width(), 100.0);
QCOMPARE(flow->height(), 120.0);
@@ -3813,7 +3816,7 @@ void tst_qquickpositioners::test_mirroring()
QQuickItem *positionerB = itemB->parentItem();
positionerA->setWidth(positionerA->width() * 2);
positionerB->setWidth(positionerB->width() * 2);
- QTRY_VERIFY(!QQuickItemPrivate::get(positionerA)->polishScheduled && !QQuickItemPrivate::get(positionerB)->polishScheduled);
+ QVERIFY(QQuickTest::qWaitForItemPolished(positionerA) && QQuickTest::qWaitForItemPolished(positionerB));
QTRY_COMPARE(itemA->x(), itemB->x());
}
@@ -3841,7 +3844,7 @@ void tst_qquickpositioners::test_allInvisible()
QVERIFY(root);
QQuickRow *row = window->rootObject()->findChild<QQuickRow*>("row");
- QVERIFY(row != 0);
+ QVERIFY(row != nullptr);
QCOMPARE(row->width(), qreal(0));
QCOMPARE(row->height(), qreal(0));
@@ -3856,7 +3859,7 @@ void tst_qquickpositioners::test_allInvisible()
QCOMPARE(row->width(), 7.0);
QQuickColumn *column = window->rootObject()->findChild<QQuickColumn*>("column");
- QVERIFY(column != 0);
+ QVERIFY(column != nullptr);
QCOMPARE(column->width(), qreal(0));
QCOMPARE(column->height(), qreal(0));
@@ -3871,7 +3874,7 @@ void tst_qquickpositioners::test_allInvisible()
QCOMPARE(column->width(), 7.0);
QQuickGrid *grid = window->rootObject()->findChild<QQuickGrid*>("grid");
- QVERIFY(grid != 0);
+ QVERIFY(grid != nullptr);
QCOMPARE(grid->width(), qreal(0));
QCOMPARE(grid->height(), qreal(0));
@@ -3886,7 +3889,7 @@ void tst_qquickpositioners::test_allInvisible()
QCOMPARE(grid->width(), 7.0);
QQuickFlow *flow = window->rootObject()->findChild<QQuickFlow*>("flow");
- QVERIFY(flow != 0);
+ QVERIFY(flow != nullptr);
QCOMPARE(flow->width(), qreal(0));
QCOMPARE(flow->height(), qreal(0));
@@ -3906,10 +3909,10 @@ void tst_qquickpositioners::test_attachedproperties()
QFETCH(QString, filename);
QScopedPointer<QQuickView> window(createView(filename));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickRectangle *greenRect = window->rootObject()->findChild<QQuickRectangle *>("greenRect");
- QVERIFY(greenRect != 0);
+ QVERIFY(greenRect != nullptr);
int posIndex = greenRect->property("posIndex").toInt();
QCOMPARE(posIndex, 0);
@@ -3919,7 +3922,7 @@ void tst_qquickpositioners::test_attachedproperties()
QVERIFY(!isLast);
QQuickRectangle *yellowRect = window->rootObject()->findChild<QQuickRectangle *>("yellowRect");
- QVERIFY(yellowRect != 0);
+ QVERIFY(yellowRect != nullptr);
posIndex = yellowRect->property("posIndex").toInt();
QCOMPARE(posIndex, -1);
@@ -3952,13 +3955,13 @@ void tst_qquickpositioners::test_attachedproperties_data()
void tst_qquickpositioners::test_attachedproperties_dynamic()
{
QScopedPointer<QQuickView> window(createView(testFile("attachedproperties-dynamic.qml")));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickRow *row = window->rootObject()->findChild<QQuickRow *>("pos");
- QVERIFY(row != 0);
+ QVERIFY(row != nullptr);
QQuickRectangle *rect0 = window->rootObject()->findChild<QQuickRectangle *>("rect0");
- QVERIFY(rect0 != 0);
+ QVERIFY(rect0 != nullptr);
int posIndex = rect0->property("index").toInt();
QCOMPARE(posIndex, 0);
@@ -3968,7 +3971,7 @@ void tst_qquickpositioners::test_attachedproperties_dynamic()
QVERIFY(!isLast);
QQuickRectangle *rect1 = window->rootObject()->findChild<QQuickRectangle *>("rect1");
- QVERIFY(rect1 != 0);
+ QVERIFY(rect1 != nullptr);
posIndex = rect1->property("index").toInt();
QCOMPARE(posIndex, 1);
@@ -3984,7 +3987,7 @@ void tst_qquickpositioners::test_attachedproperties_dynamic()
QTRY_VERIFY(!rect1->property("lastItem").toBool());
QQuickRectangle *rect2 = window->rootObject()->findChild<QQuickRectangle *>("rect2");
- QVERIFY(rect2 != 0);
+ QVERIFY(rect2 != nullptr);
posIndex = rect2->property("index").toInt();
QCOMPARE(posIndex, 2);
@@ -3995,7 +3998,7 @@ void tst_qquickpositioners::test_attachedproperties_dynamic()
row->metaObject()->invokeMethod(row, "destroySubRect");
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
QTRY_COMPARE(rect1->property("index").toInt(), 1);
@@ -4006,16 +4009,20 @@ void tst_qquickpositioners::test_attachedproperties_dynamic()
QQuickView *tst_qquickpositioners::createView(const QString &filename, bool wait)
{
- QQuickView *window = new QQuickView(0);
- qDebug() << "1";
+ QQuickView *window = new QQuickView(nullptr);
+ qCDebug(lcTests) << "created window";
window->setSource(QUrl::fromLocalFile(filename));
- qDebug() << "2";
+ qCDebug(lcTests) << "loaded content from" << filename;
window->show();
- qDebug() << "3";
+ qCDebug(lcTests) << "window shown";
+ bool exposed = true;
if (wait)
- QTest::qWaitForWindowExposed(window); //It may not relayout until the next frame, so it needs to be drawn
- qDebug() << "4";
+ exposed = QTest::qWaitForWindowExposed(window); //It may not relayout until the next frame, so it needs to be drawn
+ if (exposed)
+ qCDebug(lcTests) << "window exposed";
+ else
+ qCWarning(lcTests) << "window NOT exposed";
return window;
}
diff --git a/tests/auto/quick/qquickrectangle/data/gradient-preset.qml b/tests/auto/quick/qquickrectangle/data/gradient-preset.qml
new file mode 100644
index 0000000000..b740bdd610
--- /dev/null
+++ b/tests/auto/quick/qquickrectangle/data/gradient-preset.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Item {
+ Rectangle {
+ objectName: "enum"
+ gradient: Gradient.NightFade
+ }
+ Rectangle {
+ objectName: "string"
+ gradient: "NightFade"
+ }
+ Rectangle {
+ objectName: "invalid"
+ gradient: -1
+ }
+}
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index 0d79592e37..f6ca999cf5 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -49,6 +49,7 @@ private slots:
void gradient_border();
void gradient_separate();
void gradient_multiple();
+ void gradient_preset();
void antialiasing();
private:
@@ -70,6 +71,10 @@ void tst_qquickrectangle::color()
QVERIFY(QTest::qWaitForWindowExposed(&view));
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
QImage image = view.grabWindow();
QVERIFY(image.pixel(0,0) == QColor("#020202").rgba());
}
@@ -80,7 +85,7 @@ void tst_qquickrectangle::gradient()
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(component.create());
QVERIFY(rect);
- QQuickGradient *grad = rect->gradient();
+ QQuickGradient *grad = qobject_cast<QQuickGradient *>(rect->gradient().toQObject());
QVERIFY(grad);
QQmlListProperty<QQuickGradientStop> stops = grad->stops();
@@ -99,7 +104,7 @@ void tst_qquickrectangle::gradient()
QMetaObject::invokeMethod(rect, "resetGradient");
- grad = rect->gradient();
+ grad = qobject_cast<QQuickGradient *>(rect->gradient().toQObject());
QVERIFY(!grad);
delete rect;
@@ -170,6 +175,29 @@ void tst_qquickrectangle::gradient_multiple()
QVERIFY(secondIsDirty);
}
+void tst_qquickrectangle::gradient_preset()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("gradient-preset.qml"));
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ QQuickRectangle *enumRect = view.rootObject()->findChild<QQuickRectangle *>("enum");
+ QVERIFY(enumRect);
+ QVERIFY(enumRect->gradient().isNumber());
+ QCOMPARE(enumRect->gradient().toUInt(), QGradient::NightFade);
+
+ QQuickRectangle *stringRect = view.rootObject()->findChild<QQuickRectangle *>("string");
+ QVERIFY(stringRect);
+ QVERIFY(stringRect->gradient().isString());
+ QCOMPARE(stringRect->gradient().toString(), QLatin1String("NightFade"));
+
+ QQuickRectangle *invalidRect = view.rootObject()->findChild<QQuickRectangle *>("invalid");
+ QVERIFY(invalidRect);
+ QVERIFY(invalidRect->gradient().isUndefined());
+}
+
void tst_qquickrectangle::antialiasing()
{
QQmlComponent component(&engine);
diff --git a/tests/auto/quick/qquickrepeater/data/asynchronousMove.qml b/tests/auto/quick/qquickrepeater/data/asynchronousMove.qml
new file mode 100644
index 0000000000..02499c8531
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/asynchronousMove.qml
@@ -0,0 +1,51 @@
+import QtQuick 2.3
+import QtQuick.Window 2.2
+
+Item {
+ property bool finished: loader.status === Loader.Ready && loader.progress === 1
+
+ ListModel {
+ id: listModel
+ ListElement { i:0 }
+ ListElement { i:1 }
+ ListElement { i:2 }
+ ListElement { i:3 }
+ }
+
+ Timer {
+ running: true
+ interval: 1
+ repeat: count < 5
+ property int count : 0
+
+ onTriggered: {
+ listModel.move(listModel.count - 1, listModel.count - 2, 1)
+ ++count
+ }
+ }
+
+ Loader {
+ id: loader
+ asynchronous: true
+ sourceComponent: Row {
+ spacing: 4
+ Repeater {
+ model: listModel
+ delegate: Column {
+ spacing: 4
+ Repeater {
+ model: 4
+ delegate: Rectangle {
+ width: 30
+ height: 30
+ color: "blue"
+ Component.onCompleted: {
+ ctrl.wait()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/data/itemlist.qml b/tests/auto/quick/qquickrepeater/data/itemlist.qml
index 174bfd4d18..12470f9fd9 100644
--- a/tests/auto/quick/qquickrepeater/data/itemlist.qml
+++ b/tests/auto/quick/qquickrepeater/data/itemlist.qml
@@ -1,7 +1,8 @@
// This example demonstrates placing items in a view using
-// a VisualItemModel
+// an ObjectModel
import QtQuick 2.0
+import QtQml.Models 2.12
Rectangle {
id: root
@@ -22,38 +23,38 @@ Rectangle {
root.itemModel = itemModel2
}
- VisualItemModel {
+ ObjectModel {
id: itemModel1
objectName: "itemModel1"
Rectangle {
objectName: "item1"
height: 50; width: 100; color: "#FFFEF0"
- Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text1"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item2"
height: 50; width: 100; color: "#F0FFF7"
- Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text2"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item3"
height: 50; width: 100; color: "#F4F0FF"
- Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text3"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
}
- VisualItemModel {
+ ObjectModel {
id: itemModel2
objectName: "itemModel2"
Rectangle {
objectName: "item4"
height: 50; width: 100; color: "#FFFEF0"
- Text { objectName: "text4"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text4"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
Rectangle {
objectName: "item5"
height: 50; width: 100; color: "#F0FFF7"
- Text { objectName: "text5"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+ Text { objectName: "text5"; text: "index: " + parent.ObjectModel.index; font.bold: true; anchors.centerIn: parent }
}
}
diff --git a/tests/auto/quick/qquickrepeater/data/ownership.qml b/tests/auto/quick/qquickrepeater/data/ownership.qml
new file mode 100644
index 0000000000..e13df3ab3a
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/ownership.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.0
+
+Repeater {
+}
diff --git a/tests/auto/quick/qquickrepeater/data/package.qml b/tests/auto/quick/qquickrepeater/data/package.qml
new file mode 100644
index 0000000000..1f9eb0d970
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/package.qml
@@ -0,0 +1,35 @@
+import QtQuick 2.0
+import QtQml.Models 2.2
+import QtQuick.Window 2.0
+
+Window {
+ width: 300
+ height: 300
+ visible: true
+ DelegateModel {
+ id: mdl
+
+ model: 1
+ delegate: Package {
+ Item {
+ id: first
+ Package.name: "first"
+ objectName: "firstItem"
+ }
+ Item{
+ id: second
+ Package.name: "second"
+ objectName: "secondItem"
+ }
+ }
+ }
+
+ Repeater {
+ id: repeater1
+ model: mdl.parts.first
+ }
+ Repeater {
+ id: repeater2
+ model: mdl.parts.second
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/data/visualitemmodel.qml b/tests/auto/quick/qquickrepeater/data/visualitemmodel.qml
index b1b7b97881..0fb930449a 100644
--- a/tests/auto/quick/qquickrepeater/data/visualitemmodel.qml
+++ b/tests/auto/quick/qquickrepeater/data/visualitemmodel.qml
@@ -1,10 +1,11 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Rectangle {
width: 360
height: 360
- VisualItemModel {
+ ObjectModel {
id: visItemModel
Rectangle {
width: 20
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index f7b04e9a30..e4b427f6ec 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -37,6 +37,7 @@
#include <QtQuick/private/qquicktext_p.h>
#include <QtQml/private/qqmllistmodel_p.h>
#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <QtGui/qstandarditemmodel.h>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
@@ -75,6 +76,9 @@ private slots:
void destroyCount();
void stackingOrder();
void objectModel();
+ void QTBUG54859_asynchronousMove();
+ void package();
+ void ownership();
};
class TestObject : public QObject
@@ -118,7 +122,7 @@ void tst_QQuickRepeater::numberModel()
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QCOMPARE(repeater->parentItem()->childItems().count(), 5+1);
QVERIFY(!repeater->itemAt(-1));
@@ -129,6 +133,12 @@ void tst_QQuickRepeater::numberModel()
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
QVERIFY(!testObject->error());
+ ctxt->setContextProperty("testData", std::numeric_limits<int>::max());
+ QCOMPARE(repeater->parentItem()->childItems().count(), 1);
+
+ ctxt->setContextProperty("testData", -1234);
+ QCOMPARE(repeater->parentItem()->childItems().count(), 1);
+
delete testObject;
delete window;
}
@@ -159,7 +169,7 @@ void tst_QQuickRepeater::objectList()
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QCOMPARE(repeater->property("errors").toInt(), 0);//If this fails either they are out of order or can't find the object's data
QCOMPARE(repeater->property("instantiated").toInt(), 100);
@@ -200,10 +210,10 @@ void tst_QQuickRepeater::stringList()
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QQuickItem *container = findItem<QQuickItem>(window->rootObject(), "container");
- QVERIFY(container != 0);
+ QVERIFY(container != nullptr);
QCOMPARE(container->childItems().count(), data.count() + 3);
@@ -212,7 +222,7 @@ void tst_QQuickRepeater::stringList()
if (i == 0) {
QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), QLatin1String("Zero"));
} else if (i == container->childItems().count() - 2) {
// The repeater itself
@@ -222,11 +232,11 @@ void tst_QQuickRepeater::stringList()
continue;
} else if (i == container->childItems().count() - 1) {
QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), QLatin1String("Last"));
} else {
QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), data.at(i-1));
}
}
@@ -248,9 +258,9 @@ void tst_QQuickRepeater::dataModel_adding()
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QQuickItem *container = findItem<QQuickItem>(window->rootObject(), "container");
- QVERIFY(container != 0);
+ QVERIFY(container != nullptr);
QVERIFY(!repeater->itemAt(0));
@@ -330,9 +340,9 @@ void tst_QQuickRepeater::dataModel_removing()
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QQuickItem *container = findItem<QQuickItem>(window->rootObject(), "container");
- QVERIFY(container != 0);
+ QVERIFY(container != nullptr);
QCOMPARE(container->childItems().count(), repeater->count()+1);
QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
@@ -396,9 +406,9 @@ void tst_QQuickRepeater::dataModel_changes()
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QQuickItem *container = findItem<QQuickItem>(window->rootObject(), "container");
- QVERIFY(container != 0);
+ QVERIFY(container != nullptr);
QCOMPARE(container->childItems().count(), repeater->count()+1);
// Check that model changes are propagated
@@ -430,10 +440,10 @@ void tst_QQuickRepeater::itemModel()
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QQuickItem *container = findItem<QQuickItem>(window->rootObject(), "container");
- QVERIFY(container != 0);
+ QVERIFY(container != nullptr);
QCOMPARE(container->childItems().count(), 1);
@@ -473,9 +483,9 @@ void tst_QQuickRepeater::resetModel()
window->setSource(testFileUrl("repeater1.qml"));
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QQuickItem *container = findItem<QQuickItem>(window->rootObject(), "container");
- QVERIFY(container != 0);
+ QVERIFY(container != nullptr);
QCOMPARE(repeater->count(), dataA.count());
for (int i=0; i<repeater->count(); i++)
@@ -566,9 +576,9 @@ void tst_QQuickRepeater::modelReset()
QVERIFY(rootItem);
QQuickRepeater *repeater = findItem<QQuickRepeater>(rootItem, "repeater");
- QVERIFY(repeater != 0);
+ QVERIFY(repeater != nullptr);
QQuickItem *container = findItem<QQuickItem>(rootItem, "container");
- QVERIFY(container != 0);
+ QVERIFY(container != nullptr);
QCOMPARE(repeater->count(), 0);
@@ -700,7 +710,7 @@ void tst_QQuickRepeater::asynchronous()
container = findItem<QQuickItem>(rootObject, "container");
}
- QQuickRepeater *repeater = 0;
+ QQuickRepeater *repeater = nullptr;
while (!repeater) {
bool b = false;
controller.incubateWhile(&b);
@@ -712,8 +722,8 @@ void tst_QQuickRepeater::asynchronous()
for (int i = 9; i >= 0; --i) {
QString name("delegate");
name += QString::number(i);
- QVERIFY(findItem<QQuickItem>(container, name) == 0);
- QQuickItem *item = 0;
+ QVERIFY(findItem<QQuickItem>(container, name) == nullptr);
+ QQuickItem *item = nullptr;
while (!item) {
bool b = false;
controller.incubateWhile(&b);
@@ -803,7 +813,7 @@ void tst_QQuickRepeater::invalidContextCrash()
// deleted first and then the repeater. During deletion the QML context
// has been deleted already and is invalid.
model->setParent(root.data());
- repeater->setParent(0);
+ repeater->setParent(nullptr);
repeater->setParent(root.data());
QCOMPARE(root->children().count(), 2);
@@ -812,7 +822,7 @@ void tst_QQuickRepeater::invalidContextCrash()
// Delete the root object, which will invalidate/delete the QML context
// and then delete the child QObjects, which may try to access the context.
- root.reset(0);
+ root.reset(nullptr);
}
void tst_QQuickRepeater::jsArrayChange()
@@ -989,6 +999,115 @@ void tst_QQuickRepeater::objectModel()
delete positioner;
}
+class Ctrl : public QObject
+{
+ Q_OBJECT
+public:
+
+ Q_INVOKABLE void wait()
+ {
+ QTest::qWait(200);
+ }
+};
+
+void tst_QQuickRepeater::QTBUG54859_asynchronousMove()
+{
+ Ctrl ctrl;
+ QQuickView* view = createView();
+ view->rootContext()->setContextProperty("ctrl", &ctrl);
+ view->setSource(testFileUrl("asynchronousMove.qml"));
+ view->show();
+ QQuickItem* item = view->rootObject();
+
+
+ QTRY_COMPARE(item->property("finished"), QVariant(true));
+}
+
+void tst_QQuickRepeater::package()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("package.qml"));
+
+ QScopedPointer<QObject>o(component.create()); // don't crash!
+ QVERIFY(o != nullptr);
+
+ {
+ QQuickRepeater *repeater1 = qobject_cast<QQuickRepeater*>(qmlContext(o.data())->contextProperty("repeater1").value<QObject*>());
+ QVERIFY(repeater1);
+ QCOMPARE(repeater1->count(), 1);
+ QCOMPARE(repeater1->itemAt(0)->objectName(), "firstItem");
+ }
+
+ {
+ QQuickRepeater *repeater2 = qobject_cast<QQuickRepeater*>(qmlContext(o.data())->contextProperty("repeater2").value<QObject*>());
+ QVERIFY(repeater2);
+ QCOMPARE(repeater2->count(), 1);
+ QCOMPARE(repeater2->itemAt(0)->objectName(), "secondItem");
+ }
+}
+
+void tst_QQuickRepeater::ownership()
+{
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("ownership.qml"));
+
+ QScopedPointer<QAbstractItemModel> aim(new QStandardItemModel);
+ QPointer<QAbstractItemModel> modelGuard(aim.data());
+ QQmlEngine::setObjectOwnership(aim.data(), QQmlEngine::JavaScriptOwnership);
+ {
+ QJSValue wrapper = engine.newQObject(aim.data());
+ }
+
+ QScopedPointer<QObject> repeater(component.create());
+ QVERIFY(!repeater.isNull());
+
+ QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(aim.data()));
+
+ repeater->setProperty("model", QVariant::fromValue<QObject*>(aim.data()));
+
+ QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(aim.data()));
+
+ engine.collectGarbage();
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ QVERIFY(modelGuard);
+
+ QScopedPointer<QQmlComponent> delegate(new QQmlComponent(&engine));
+ delegate->setData(QByteArrayLiteral("import QtQuick 2.0\nItem{}"), dataDirectoryUrl().resolved(QUrl("inline.qml")));
+ QPointer<QQmlComponent> delegateGuard(delegate.data());
+ QQmlEngine::setObjectOwnership(delegate.data(), QQmlEngine::JavaScriptOwnership);
+ {
+ QJSValue wrapper = engine.newQObject(delegate.data());
+ }
+
+ QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(delegate.data()));
+
+ repeater->setProperty("delegate", QVariant::fromValue<QObject*>(delegate.data()));
+
+ QVERIFY(!QQmlData::keepAliveDuringGarbageCollection(delegate.data()));
+
+ engine.collectGarbage();
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ QVERIFY(delegateGuard);
+
+ repeater->setProperty("model", QVariant());
+ repeater->setProperty("delegate", QVariant());
+
+ QVERIFY(delegateGuard);
+ QVERIFY(modelGuard);
+
+ delegate.take();
+ aim.take();
+
+ engine.collectGarbage();
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ QVERIFY(!delegateGuard);
+ QVERIFY(!modelGuard);
+}
+
QTEST_MAIN(tst_QQuickRepeater)
#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/quick/qquickshadereffect/data/MyIcon.qml b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
index b83da321f2..eb788fce7a 100644
--- a/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
+++ b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
** Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
index d1292f74b8..46d81f2106 100644
--- a/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
+++ b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
@@ -1,12 +1,22 @@
/****************************************************************************
**
** Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
index fe33dbd4d8..a57b7d4c1f 100644
--- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
@@ -46,14 +46,18 @@ class TestShaderEffect : public QQuickShaderEffect
Q_PROPERTY(QMatrix4x4 mat4x4 READ mat4x4Read NOTIFY dummyChanged)
public:
+ TestShaderEffect(QQuickItem* parent = nullptr) : QQuickShaderEffect(parent)
+ {
+ }
+
QMatrix4x4 mat4x4Read() const { return QMatrix4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1); }
QVariant dummyRead() const { return QVariant(); }
int signalsConnected = 0;
protected:
- void connectNotify(const QMetaMethod &) { ++signalsConnected; }
- void disconnectNotify(const QMetaMethod &) { --signalsConnected; }
+ void connectNotify(const QMetaMethod &) override { ++signalsConnected; }
+ void disconnectNotify(const QMetaMethod &) override { --signalsConnected; }
signals:
void dummyChanged();
@@ -79,6 +83,8 @@ private slots:
void deleteShaderEffectSource();
void twoImagesOneShaderEffect();
+ void withoutQmlEngine();
+
private:
enum PresenceFlags {
VertexPresent = 0x01,
@@ -257,7 +263,7 @@ void tst_qquickshadereffect::lookThroughShaderCode()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nimport ShaderEffectTest 1.0\nTestShaderEffect {}", QUrl());
QScopedPointer<TestShaderEffect> item(qobject_cast<TestShaderEffect*>(component.create()));
- QCOMPARE(item->signalsConnected, 1);
+ QCOMPARE(item->signalsConnected, 0);
QString expected;
if ((presenceFlags & VertexPresent) == 0)
@@ -274,13 +280,13 @@ void tst_qquickshadereffect::lookThroughShaderCode()
QCOMPARE(item->parseLog(), expected);
// If the uniform was successfully parsed, the notify signal has been connected to an update slot.
- QCOMPARE(item->signalsConnected, (presenceFlags & SourcePresent) ? 2 : 1);
+ QCOMPARE(item->signalsConnected, (presenceFlags & SourcePresent) ? 1 : 0);
}
void tst_qquickshadereffect::deleteSourceItem()
{
// purely to ensure that deleting the sourceItem of a shader doesn't cause a crash
- QQuickView *view = new QQuickView(0);
+ QQuickView *view = new QQuickView(nullptr);
view->setSource(QUrl::fromLocalFile(testFile("deleteSourceItem.qml")));
view->show();
QVERIFY(QTest::qWaitForWindowExposed(view));
@@ -295,7 +301,7 @@ void tst_qquickshadereffect::deleteSourceItem()
void tst_qquickshadereffect::deleteShaderEffectSource()
{
// purely to ensure that deleting the sourceItem of a shader doesn't cause a crash
- QQuickView *view = new QQuickView(0);
+ QQuickView *view = new QQuickView(nullptr);
view->setSource(QUrl::fromLocalFile(testFile("deleteShaderEffectSource.qml")));
view->show();
QVERIFY(QTest::qWaitForWindowExposed(view));
@@ -310,7 +316,7 @@ void tst_qquickshadereffect::deleteShaderEffectSource()
void tst_qquickshadereffect::twoImagesOneShaderEffect()
{
// purely to ensure that deleting the sourceItem of a shader doesn't cause a crash
- QQuickView *view = new QQuickView(0);
+ QQuickView *view = new QQuickView(nullptr);
view->setSource(QUrl::fromLocalFile(testFile("twoImagesOneShaderEffect.qml")));
view->show();
QVERIFY(QTest::qWaitForWindowExposed(view));
@@ -320,6 +326,16 @@ void tst_qquickshadereffect::twoImagesOneShaderEffect()
delete view;
}
+void tst_qquickshadereffect::withoutQmlEngine()
+{
+ // using a shader without QML engine used to crash
+ auto window = new QQuickWindow;
+ auto shaderEffect = new TestShaderEffect(window->contentItem());
+ shaderEffect->setVertexShader("");
+ QVERIFY(shaderEffect->isComponentComplete());
+ delete window;
+}
+
QTEST_MAIN(tst_qquickshadereffect)
#include "tst_qquickshadereffect.moc"
diff --git a/tests/auto/quick/qquickshape/BLACKLIST b/tests/auto/quick/qquickshape/BLACKLIST
new file mode 100644
index 0000000000..d0ebc2f505
--- /dev/null
+++ b/tests/auto/quick/qquickshape/BLACKLIST
@@ -0,0 +1,8 @@
+[render]
+osx ci
+[renderWithMultipleSp]
+osx ci
+[radialGrad]
+osx ci
+[conicalGrad]
+osx ci
diff --git a/tests/auto/quick/qquickshape/data/pathitem5.png b/tests/auto/quick/qquickshape/data/pathitem5.png
new file mode 100644
index 0000000000..cb5cfd25dc
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem5.png
Binary files differ
diff --git a/tests/auto/quick/qquickshape/data/pathitem5.qml b/tests/auto/quick/qquickshape/data/pathitem5.qml
new file mode 100644
index 0000000000..1bd465d5c0
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem5.qml
@@ -0,0 +1,37 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Item {
+ width: 200
+ height: 150
+
+ Shape {
+ vendorExtensionsEnabled: false
+ objectName: "pathItem"
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: RadialGradient {
+ centerX: 100; centerY: 100; centerRadius: 100
+ focalX: 100; focalY: 100; focalRadius: 10
+ GradientStop { position: 0; color: "#ffffff" }
+ GradientStop { position: 0.11; color: "#f9ffa0" }
+ GradientStop { position: 0.13; color: "#f9ff99" }
+ GradientStop { position: 0.14; color: "#f3ff86" }
+ GradientStop { position: 0.49; color: "#93b353" }
+ GradientStop { position: 0.87; color: "#264619" }
+ GradientStop { position: 0.96; color: "#0c1306" }
+ GradientStop { position: 1; color: "#000000" }
+ }
+ fillColor: "blue" // ignored with the gradient set
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 20; startY: 20
+ PathLine { x: 180; y: 130 }
+ PathLine { x: 20; y: 130 }
+ PathLine { x: 20; y: 20 }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshape/data/pathitem6.png b/tests/auto/quick/qquickshape/data/pathitem6.png
new file mode 100644
index 0000000000..d9e53d6c00
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem6.png
Binary files differ
diff --git a/tests/auto/quick/qquickshape/data/pathitem6.qml b/tests/auto/quick/qquickshape/data/pathitem6.qml
new file mode 100644
index 0000000000..fafcc48196
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem6.qml
@@ -0,0 +1,35 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Item {
+ width: 200
+ height: 150
+
+ Shape {
+ vendorExtensionsEnabled: false
+ objectName: "pathItem"
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: ConicalGradient {
+ centerX: 100; centerY: 100; angle: 45
+ GradientStop { position: 0; color: "#00000000" }
+ GradientStop { position: 0.10; color: "#ffe0cc73" }
+ GradientStop { position: 0.17; color: "#ffc6a006" }
+ GradientStop { position: 0.46; color: "#ff600659" }
+ GradientStop { position: 0.72; color: "#ff0680ac" }
+ GradientStop { position: 0.92; color: "#ffb9d9e6" }
+ GradientStop { position: 1.00; color: "#00000000" }
+ }
+ fillColor: "blue" // ignored with the gradient set
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 20; startY: 20
+ PathLine { x: 180; y: 130 }
+ PathLine { x: 20; y: 130 }
+ PathLine { x: 20; y: 20 }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshape/qquickshape.pro b/tests/auto/quick/qquickshape/qquickshape.pro
index 29c3502b86..a0e5c002e0 100644
--- a/tests/auto/quick/qquickshape/qquickshape.pro
+++ b/tests/auto/quick/qquickshape/qquickshape.pro
@@ -9,27 +9,5 @@ include (../shared/util.pri)
TESTDATA = data/*
-HEADERS += \
- ../../../../src/imports/shapes/qquickshape_p.h \
- ../../../../src/imports/shapes/qquickshape_p_p.h \
- ../../../../src/imports/shapes/qquickshapegenericrenderer_p.h \
- ../../../../src/imports/shapes/qquickshapesoftwarerenderer_p.h
-
-SOURCES += \
- ../../../../src/imports/shapes/qquickshape.cpp \
- ../../../../src/imports/shapes/qquickshapegenericrenderer.cpp \
- ../../../../src/imports/shapes/qquickshapesoftwarerenderer.cpp
-
-qtConfig(opengl) {
- HEADERS += \
- ../../../../src/imports/shapes/qquicknvprfunctions_p.h \
- ../../../../src/imports/shapes/qquicknvprfunctions_p_p.h \
- ../../../../src/imports/shapes/qquickshapenvprrenderer_p.h
-
- SOURCES += \
- ../../../../src/imports/shapes/qquicknvprfunctions.cpp \
- ../../../../src/imports/shapes/qquickshapenvprrenderer.cpp
-}
-
-QT += core-private gui-private qml-private quick-private testlib
+QT += core-private gui-private qml-private quick-private testlib quickshapes-private
qtHaveModule(widgets): QT += widgets
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index dcc79e6599..61fb260612 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -33,7 +33,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlincubator.h>
-#include "../../../../src/imports/shapes/qquickshape_p.h"
+#include <QtQuickShapes/private/qquickshape_p.h>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
@@ -55,6 +55,8 @@ private slots:
void changeSignals();
void render();
void renderWithMultipleSp();
+ void radialGrad();
+ void conicalGrad();
};
tst_QQuickShape::tst_QQuickShape()
@@ -67,6 +69,8 @@ tst_QQuickShape::tst_QQuickShape()
qmlRegisterType<QQuickShapePath>(uri, 1, 0, "ShapePath");
qmlRegisterUncreatableType<QQuickShapeGradient>(uri, 1, 0, "ShapeGradient", QQuickShapeGradient::tr("ShapeGradient is an abstract base class"));
qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient");
+ qmlRegisterType<QQuickShapeRadialGradient>(uri, 1, 0, "RadialGradient");
+ qmlRegisterType<QQuickShapeConicalGradient>(uri, 1, 0, "ConicalGradient");
}
void tst_QQuickShape::initValues()
@@ -78,7 +82,7 @@ void tst_QQuickShape::initValues()
QVERIFY(obj != nullptr);
QVERIFY(obj->rendererType() == QQuickShape::UnknownRenderer);
QVERIFY(!obj->asynchronous());
- QVERIFY(obj->vendorExtensionsEnabled());
+ QVERIFY(!obj->vendorExtensionsEnabled());
QVERIFY(obj->status() == QQuickShape::Null);
auto vps = obj->data();
QVERIFY(vps.count(&vps) == 0);
@@ -95,7 +99,7 @@ void tst_QQuickShape::vpInitValues()
QVERIFY(obj != nullptr);
QVERIFY(obj->rendererType() == QQuickShape::UnknownRenderer);
QVERIFY(!obj->asynchronous());
- QVERIFY(obj->vendorExtensionsEnabled());
+ QVERIFY(!obj->vendorExtensionsEnabled());
QVERIFY(obj->status() == QQuickShape::Null);
auto vps = obj->data();
QVERIFY(vps.count(&vps) == 2);
@@ -219,13 +223,20 @@ void tst_QQuickShape::render()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
QImage refImg(testFileUrl("pathitem3.png").toLocalFile());
QVERIFY(!refImg.isNull());
- QVERIFY(QQuickVisualTestUtil::compareImages(img.convertToFormat(refImg.format()), refImg));
+ QString errorMessage;
+ const QImage actualImg = img.convertToFormat(refImg.format());
+ QVERIFY2(QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage),
+ qPrintable(errorMessage));
}
void tst_QQuickShape::renderWithMultipleSp()
@@ -236,13 +247,68 @@ void tst_QQuickShape::renderWithMultipleSp()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
QImage refImg(testFileUrl("pathitem4.png").toLocalFile());
QVERIFY(!refImg.isNull());
- QVERIFY(QQuickVisualTestUtil::compareImages(img.convertToFormat(refImg.format()), refImg));
+ QString errorMessage;
+ const QImage actualImg = img.convertToFormat(refImg.format());
+ QVERIFY2(QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage),
+ qPrintable(errorMessage));
+}
+
+void tst_QQuickShape::radialGrad()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem5.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("pathitem5.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QString errorMessage;
+ const QImage actualImg = img.convertToFormat(refImg.format());
+ QVERIFY2(QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage),
+ qPrintable(errorMessage));
+}
+
+void tst_QQuickShape::conicalGrad()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem6.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("pathitem6.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QString errorMessage;
+ const QImage actualImg = img.convertToFormat(refImg.format());
+ QVERIFY2(QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage),
+ qPrintable(errorMessage));
}
QTEST_MAIN(tst_QQuickShape)
diff --git a/tests/auto/quick/qquickshortcut/BLACKLIST b/tests/auto/quick/qquickshortcut/BLACKLIST
new file mode 100644
index 0000000000..ba7871dc2d
--- /dev/null
+++ b/tests/auto/quick/qquickshortcut/BLACKLIST
@@ -0,0 +1,7 @@
+# QTBUG-74050
+[shortcuts]
+opensuse-42.3
+
+# QTBUG-74050
+[multiple]
+opensuse-42.3
diff --git a/tests/auto/quick/qquickshortcut/data/shortcutsRect.qml b/tests/auto/quick/qquickshortcut/data/shortcutsRect.qml
new file mode 100644
index 0000000000..9aced4e530
--- /dev/null
+++ b/tests/auto/quick/qquickshortcut/data/shortcutsRect.qml
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+
+Rectangle {
+ width: 300
+ height: 300
+
+ property string activatedShortcut
+ property string ambiguousShortcut
+
+ property alias shortcuts: repeater.model
+
+ Repeater {
+ id: repeater
+
+ Item {
+ Shortcut {
+ sequence: modelData.sequence
+ enabled: modelData.enabled
+ autoRepeat: modelData.autoRepeat
+ context: modelData.context
+ onActivated: activatedShortcut = sequence
+ onActivatedAmbiguously: ambiguousShortcut = sequence
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshortcut/qquickshortcut.pro b/tests/auto/quick/qquickshortcut/qquickshortcut.pro
index d780d9061a..018bb91594 100644
--- a/tests/auto/quick/qquickshortcut/qquickshortcut.pro
+++ b/tests/auto/quick/qquickshortcut/qquickshortcut.pro
@@ -8,3 +8,6 @@ include (../../shared/util.pri)
TESTDATA = data/*
QT += core gui qml quick testlib
+qtHaveModule(widgets) {
+ QT += quickwidgets
+}
diff --git a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
index 75ccf26af9..4962690796 100644
--- a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
+++ b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp
@@ -29,6 +29,11 @@
#include <QtTest/qtest.h>
#include <QtQuick/qquickwindow.h>
#include <QtQml/qqmlapplicationengine.h>
+#include <QtQuick/qquickitem.h>
+#include <QtTest/qsignalspy.h>
+#ifdef QT_QUICKWIDGETS_LIB
+#include <QtQuickWidgets/qquickwidget.h>
+#endif
#include "../../shared/util.h"
@@ -47,6 +52,10 @@ private slots:
void matcher();
void multiple_data();
void multiple();
+#ifdef QT_QUICKWIDGETS_LIB
+ void renderControlShortcuts_data();
+ void renderControlShortcuts();
+#endif
};
Q_DECLARE_METATYPE(Qt::Key)
@@ -453,6 +462,121 @@ void tst_QQuickShortcut::multiple()
QCOMPARE(window->property("activated").toBool(), activated);
}
+#ifdef QT_QUICKWIDGETS_LIB
+void tst_QQuickShortcut::renderControlShortcuts_data()
+{
+ QTest::addColumn<QVariantList>("shortcuts");
+ QTest::addColumn<Qt::Key>("key");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<QString>("activatedShortcut");
+ QTest::addColumn<QString>("ambiguousShortcut");
+
+ QVariantList shortcuts;
+ shortcuts << shortcutMap("M")
+ << shortcutMap("Alt+M")
+ << shortcutMap("Ctrl+M")
+ << shortcutMap("Shift+M")
+ << shortcutMap("Ctrl+Alt+M")
+ << shortcutMap("+")
+ << shortcutMap("F1")
+ << shortcutMap("Shift+F1");
+
+ QTest::newRow("M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::NoModifier) << "M" << "";
+ QTest::newRow("Alt+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::AltModifier) << "Alt+M" << "";
+ QTest::newRow("Ctrl+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ControlModifier) << "Ctrl+M" << "";
+ QTest::newRow("Shift+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Shift+M" << "";
+ QTest::newRow("Ctrl+Alt+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ControlModifier|Qt::AltModifier) << "Ctrl+Alt+M" << "";
+ QTest::newRow("+") << shortcuts << Qt::Key_Plus << Qt::KeyboardModifiers(Qt::NoModifier) << "+" << "";
+ QTest::newRow("F1") << shortcuts << Qt::Key_F1 << Qt::KeyboardModifiers(Qt::NoModifier) << "F1" << "";
+ QTest::newRow("Shift+F1") << shortcuts << Qt::Key_F1 << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Shift+F1" << "";
+
+ // ambiguous
+ shortcuts << shortcutMap("M")
+ << shortcutMap("Alt+M")
+ << shortcutMap("Ctrl+M")
+ << shortcutMap("Shift+M")
+ << shortcutMap("Ctrl+Alt+M")
+ << shortcutMap("+")
+ << shortcutMap("F1")
+ << shortcutMap("Shift+F1");
+
+ QTest::newRow("?M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::NoModifier) << "" << "M";
+ QTest::newRow("?Alt+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::AltModifier) << "" << "Alt+M";
+ QTest::newRow("?Ctrl+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ControlModifier) << "" << "Ctrl+M";
+ QTest::newRow("?Shift+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ShiftModifier) << "" << "Shift+M";
+ QTest::newRow("?Ctrl+Alt+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ControlModifier|Qt::AltModifier) << "" << "Ctrl+Alt+M";
+ QTest::newRow("?+") << shortcuts << Qt::Key_Plus << Qt::KeyboardModifiers(Qt::NoModifier) << "" << "+";
+ QTest::newRow("?F1") << shortcuts << Qt::Key_F1 << Qt::KeyboardModifiers(Qt::NoModifier) << "" << "F1";
+ QTest::newRow("?Shift+F1") << shortcuts << Qt::Key_F1 << Qt::KeyboardModifiers(Qt::ShiftModifier) << "" << "Shift+F1";
+
+ // disabled
+ shortcuts.clear();
+ shortcuts << shortcutMap("M", DisabledShortcut)
+ << shortcutMap("Alt+M", DisabledShortcut)
+ << shortcutMap("Ctrl+M", DisabledShortcut)
+ << shortcutMap("Shift+M", DisabledShortcut)
+ << shortcutMap("Ctrl+Alt+M", DisabledShortcut)
+ << shortcutMap("+", DisabledShortcut)
+ << shortcutMap("F1", DisabledShortcut)
+ << shortcutMap("Shift+F1", DisabledShortcut);
+
+ QTest::newRow("!M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::NoModifier) << "" << "";
+ QTest::newRow("!Alt+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::AltModifier) << "" << "";
+ QTest::newRow("!Ctrl+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ControlModifier) << "" << "";
+ QTest::newRow("!Shift+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ShiftModifier) << "" << "";
+ QTest::newRow("!Ctrl+Alt+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ControlModifier|Qt::AltModifier) << "" << "";
+ QTest::newRow("!+") << shortcuts << Qt::Key_Plus << Qt::KeyboardModifiers(Qt::NoModifier) << "" << "";
+ QTest::newRow("!F1") << shortcuts << Qt::Key_F1 << Qt::KeyboardModifiers(Qt::NoModifier) << "" << "";
+ QTest::newRow("!Shift+F1") << shortcuts << Qt::Key_F1 << Qt::KeyboardModifiers(Qt::ShiftModifier) << "" << "";
+
+ // unambigous because others disabled
+ shortcuts << shortcutMap("M")
+ << shortcutMap("Alt+M")
+ << shortcutMap("Ctrl+M")
+ << shortcutMap("Shift+M")
+ << shortcutMap("Ctrl+Alt+M")
+ << shortcutMap("+")
+ << shortcutMap("F1")
+ << shortcutMap("Shift+F1");
+
+ QTest::newRow("/M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::NoModifier) << "M" << "";
+ QTest::newRow("/Alt+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::AltModifier) << "Alt+M" << "";
+ QTest::newRow("/Ctrl+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ControlModifier) << "Ctrl+M" << "";
+ QTest::newRow("/Shift+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Shift+M" << "";
+ QTest::newRow("/Ctrl+Alt+M") << shortcuts << Qt::Key_M << Qt::KeyboardModifiers(Qt::ControlModifier|Qt::AltModifier) << "Ctrl+Alt+M" << "";
+ QTest::newRow("/+") << shortcuts << Qt::Key_Plus << Qt::KeyboardModifiers(Qt::NoModifier) << "+" << "";
+ QTest::newRow("/F1") << shortcuts << Qt::Key_F1 << Qt::KeyboardModifiers(Qt::NoModifier) << "F1" << "";
+ QTest::newRow("/Shift+F1") << shortcuts << Qt::Key_F1 << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Shift+F1" << "";
+}
+
+void tst_QQuickShortcut::renderControlShortcuts()
+{
+ QFETCH(QVariantList, shortcuts);
+ QFETCH(Qt::Key, key);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(QString, activatedShortcut);
+ QFETCH(QString, ambiguousShortcut);
+
+ QScopedPointer<QQuickWidget> quickWidget(new QQuickWidget);
+ quickWidget->resize(300,300);
+
+ QSignalSpy spy(qApp, &QGuiApplication::focusObjectChanged);
+
+ quickWidget->setSource(testFileUrl("shortcutsRect.qml"));
+ quickWidget->show();
+
+ spy.wait();
+
+ QVERIFY(qobject_cast<QQuickWidget*>(qApp->focusObject()) == quickWidget.data());
+
+ QQuickItem* item = quickWidget->rootObject();
+ item->setProperty("shortcuts", shortcuts);
+ QTest::keyPress(quickWidget->quickWindow(), key, modifiers, 1500);
+ QCOMPARE(item->property("activatedShortcut").toString(), activatedShortcut);
+ QCOMPARE(item->property("ambiguousShortcut").toString(), ambiguousShortcut);
+}
+#endif // QT_QUICKWIDGETS_LIB
+
QTEST_MAIN(tst_QQuickShortcut)
#include "tst_qquickshortcut.moc"
diff --git a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
index d78a38a662..14d2e858e8 100644
--- a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
+++ b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp
@@ -64,7 +64,7 @@ void tst_qquicksmoothedanimation::defaultValues()
QQmlComponent c(&engine, testFileUrl("smoothedanimation1.qml"));
QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->to(), 0.);
QCOMPARE(obj->velocity(), 200.);
@@ -81,7 +81,7 @@ void tst_qquicksmoothedanimation::values()
QQmlComponent c(&engine, testFileUrl("smoothedanimation2.qml"));
QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->to(), 10.);
QCOMPARE(obj->velocity(), 200.);
@@ -98,7 +98,7 @@ void tst_qquicksmoothedanimation::disabled()
QQmlComponent c(&engine, testFileUrl("smoothedanimation3.qml"));
QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->to(), 10.);
QCOMPARE(obj->velocity(), 250.);
@@ -259,7 +259,7 @@ void tst_qquicksmoothedanimation::noStart()
QQmlComponent c(&engine, testFileUrl("smoothedanimation1.qml"));
QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
obj->start();
QCOMPARE(obj->isRunning(), false);
diff --git a/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp b/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
index b4184ba1d3..9042e94c75 100644
--- a/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
+++ b/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
@@ -59,7 +59,7 @@ void tst_qquickspringanimation::defaultValues()
QQmlComponent c(&engine, testFileUrl("springanimation1.qml"));
QQuickSpringAnimation *obj = qobject_cast<QQuickSpringAnimation*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->to(), 0.);
QCOMPARE(obj->velocity(), 0.);
@@ -81,7 +81,7 @@ void tst_qquickspringanimation::values()
QQuickSpringAnimation *obj = root->findChild<QQuickSpringAnimation*>();
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->to(), 1.44);
QCOMPARE(obj->velocity(), 0.9);
@@ -103,7 +103,7 @@ void tst_qquickspringanimation::disabled()
QQmlComponent c(&engine, testFileUrl("springanimation3.qml"));
QQuickSpringAnimation *obj = qobject_cast<QQuickSpringAnimation*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->to(), 1.44);
QCOMPARE(obj->velocity(), 0.9);
diff --git a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
index 08674c528a..e5d55a6871 100644
--- a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
+++ b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
@@ -47,7 +47,7 @@ private slots:
void tst_qquickspritesequence::test_properties()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("basic.qml"));
window->show();
@@ -75,7 +75,7 @@ void tst_qquickspritesequence::test_huge()
The large allocations of memory involved and separate codepath does make
a doesn't crash test worthwhile.
*/
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("huge.qml"));
window->show();
@@ -90,7 +90,7 @@ void tst_qquickspritesequence::test_huge()
void tst_qquickspritesequence::test_framerateAdvance()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("advance.qml"));
window->show();
@@ -106,7 +106,7 @@ void tst_qquickspritesequence::test_framerateAdvance()
void tst_qquickspritesequence::test_jumpToCrash()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("crashonstart.qml"));
window->show();
@@ -118,7 +118,7 @@ void tst_qquickspritesequence::test_jumpToCrash()
void tst_qquickspritesequence::test_spriteBeforeGoal()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("spritebeforegoal.qml"));
window->show();
@@ -130,7 +130,7 @@ void tst_qquickspritesequence::test_spriteBeforeGoal()
void tst_qquickspritesequence::test_spriteAfterGoal()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(testFileUrl("spriteaftergoal.qml"));
window->show();
diff --git a/tests/auto/quick/qquickstates/data/duplicateStateName.qml b/tests/auto/quick/qquickstates/data/duplicateStateName.qml
new file mode 100644
index 0000000000..7bfafbef1b
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/duplicateStateName.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+Rectangle {
+ property bool condition1: false
+ property bool condition2: false
+ property bool condition3: false
+
+ states: [
+ State { name: "state1"; when: condition1 },
+ State { name: "state2"; when: condition2 },
+ State { name: "state1"; when: condition3 }
+ ]
+}
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index 9b152b0676..50554f6333 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -137,6 +137,7 @@ private slots:
void revertListBug();
void QTBUG_38492();
void revertListMemoryLeak();
+ void duplicateStateName();
};
void tst_qquickstates::initTestCase()
@@ -158,7 +159,7 @@ void tst_qquickstates::basicChanges()
QQmlComponent rectComponent(&engine, testFileUrl("basicChanges.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
@@ -173,7 +174,7 @@ void tst_qquickstates::basicChanges()
QQmlComponent rectComponent(&engine, testFileUrl("basicChanges2.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
@@ -194,7 +195,7 @@ void tst_qquickstates::basicChanges()
QQmlComponent rectComponent(&engine, testFileUrl("basicChanges3.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
QCOMPARE(rect->border()->width(),1.0);
@@ -231,7 +232,7 @@ void tst_qquickstates::basicChanges()
QVERIFY(component.isReady());
MyRect *rect = qobject_cast<MyRect*>(component.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QMetaProperty prop = rect->metaObject()->property(rect->metaObject()->indexOfProperty("propertyWithNotify"));
QVERIFY(prop.hasNotifySignal());
@@ -253,7 +254,7 @@ void tst_qquickstates::attachedPropertyChanges()
QVERIFY(component.isReady());
QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != 0);
+ QVERIFY(item != nullptr);
QCOMPARE(item->width(), 50.0);
// Ensure attached property has been changed
@@ -274,7 +275,7 @@ void tst_qquickstates::basicExtension()
QQmlComponent rectComponent(&engine, testFileUrl("basicExtension.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
QCOMPARE(rect->border()->width(),1.0);
@@ -308,7 +309,7 @@ void tst_qquickstates::basicExtension()
QQmlComponent rectComponent(&engine, testFileUrl("fakeExtension.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
@@ -340,7 +341,7 @@ void tst_qquickstates::basicBinding()
QQmlComponent rectComponent(&engine, testFileUrl("basicBinding.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
@@ -368,7 +369,7 @@ void tst_qquickstates::basicBinding()
QQmlComponent rectComponent(&engine, testFileUrl("basicBinding2.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
@@ -399,7 +400,7 @@ void tst_qquickstates::basicBinding()
QQmlComponent rectComponent(&engine, testFileUrl("basicBinding3.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
rect->setProperty("sourceColor", QColor("green"));
@@ -424,7 +425,7 @@ void tst_qquickstates::basicBinding()
QQmlComponent rectComponent(&engine, testFileUrl("basicBinding4.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
@@ -456,7 +457,7 @@ void tst_qquickstates::signalOverride()
{
QQmlComponent rectComponent(&engine, testFileUrl("signalOverride.qml"));
MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
rect->doSomething();
@@ -472,7 +473,7 @@ void tst_qquickstates::signalOverride()
{
QQmlComponent rectComponent(&engine, testFileUrl("signalOverride2.qml"));
MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("white"));
rect->doSomething();
@@ -495,7 +496,7 @@ void tst_qquickstates::signalOverrideCrash()
QQmlComponent rectComponent(&engine, testFileUrl("signalOverrideCrash.qml"));
MyRect *rect = qobject_cast<MyRect*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate::get(rect)->setState("overridden");
rect->doSomething();
@@ -507,7 +508,7 @@ void tst_qquickstates::signalOverrideCrash2()
QQmlComponent rectComponent(&engine, testFileUrl("signalOverrideCrash2.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate::get(rect)->setState("state1");
QQuickItemPrivate::get(rect)->setState("state2");
@@ -522,7 +523,7 @@ void tst_qquickstates::signalOverrideCrash3()
QQmlComponent rectComponent(&engine, testFileUrl("signalOverrideCrash3.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate::get(rect)->setState("state1");
QQuickItemPrivate::get(rect)->setState("");
@@ -537,7 +538,7 @@ void tst_qquickstates::signalOverrideCrash4()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("signalOverrideCrash4.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
@@ -557,20 +558,20 @@ void tst_qquickstates::parentChange()
{
QQmlComponent rectComponent(&engine, testFileUrl("parentChange1.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QQmlListReference list(rect, "states");
QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QQuickParentChange *pChange = qobject_cast<QQuickParentChange*>(state->operationAt(0));
- QVERIFY(pChange != 0);
+ QVERIFY(pChange != nullptr);
QQuickItem *nParent = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("NewParent"));
- QVERIFY(nParent != 0);
+ QVERIFY(nParent != nullptr);
QCOMPARE(pChange->parent(), nParent);
@@ -584,10 +585,10 @@ void tst_qquickstates::parentChange()
{
QQmlComponent rectComponent(&engine, testFileUrl("parentChange2.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
rectPrivate->setState("reparented");
QCOMPARE(innerRect->rotation(), qreal(15));
@@ -599,10 +600,10 @@ void tst_qquickstates::parentChange()
{
QQmlComponent rectComponent(&engine, testFileUrl("parentChange3.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
rectPrivate->setState("reparented");
QCOMPARE(innerRect->rotation(), qreal(-37));
@@ -621,10 +622,10 @@ void tst_qquickstates::parentChange()
{
QQmlComponent rectComponent(&engine, testFileUrl("parentChange6.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QQuickItemPrivate::get(rect)->setState("reparented");
QCOMPARE(innerRect->rotation(), qreal(180));
@@ -641,10 +642,10 @@ void tst_qquickstates::parentChangeErrors()
{
QQmlComponent rectComponent(&engine, testFileUrl("parentChange4.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QTest::ignoreMessage(QtWarningMsg, fullDataPath("parentChange4.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under non-uniform scale");
QQuickItemPrivate::get(rect)->setState("reparented");
@@ -657,10 +658,10 @@ void tst_qquickstates::parentChangeErrors()
{
QQmlComponent rectComponent(&engine, testFileUrl("parentChange5.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QTest::ignoreMessage(QtWarningMsg, fullDataPath("parentChange5.qml") + ":25:9: QML ParentChange: Unable to preserve appearance under complex transform");
QQuickItemPrivate::get(rect)->setState("reparented");
@@ -677,19 +678,19 @@ void tst_qquickstates::anchorChanges()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges1.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QQmlListReference list(rect, "states");
QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
+ QVERIFY(aChanges != nullptr);
QCOMPARE(aChanges->anchors()->left().isUndefinedLiteral(), true);
QVERIFY(!aChanges->anchors()->left().isEmpty());
@@ -714,11 +715,11 @@ void tst_qquickstates::anchorChanges2()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
rectPrivate->setState("right");
QCOMPARE(innerRect->x(), qreal(150));
@@ -735,25 +736,25 @@ void tst_qquickstates::anchorChanges3()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
- QVERIFY(leftGuideline != 0);
+ QVERIFY(leftGuideline != nullptr);
QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
- QVERIFY(bottomGuideline != 0);
+ QVERIFY(bottomGuideline != nullptr);
QQmlListReference list(rect, "states");
QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
+ QVERIFY(aChanges != nullptr);
QVERIFY(!aChanges->anchors()->top().isEmpty());
QVERIFY(!aChanges->anchors()->bottom().isEmpty());
@@ -789,24 +790,24 @@ void tst_qquickstates::anchorChanges4()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges4.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
- QVERIFY(leftGuideline != 0);
+ QVERIFY(leftGuideline != nullptr);
QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
- QVERIFY(bottomGuideline != 0);
+ QVERIFY(bottomGuideline != nullptr);
QQmlListReference list(rect, "states");
QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
+ QVERIFY(aChanges != nullptr);
QVERIFY(!aChanges->anchors()->horizontalCenter().isEmpty());
QVERIFY(!aChanges->anchors()->verticalCenter().isEmpty());
@@ -827,24 +828,24 @@ void tst_qquickstates::anchorChanges5()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges5.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
- QVERIFY(leftGuideline != 0);
+ QVERIFY(leftGuideline != nullptr);
QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
- QVERIFY(bottomGuideline != 0);
+ QVERIFY(bottomGuideline != nullptr);
QQmlListReference list(rect, "states");
QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
+ QVERIFY(aChanges != nullptr);
QVERIFY(!aChanges->anchors()->baseline().isEmpty());
@@ -873,20 +874,20 @@ void tst_qquickstates::anchorChangesRTL()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges1.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
mirrorAnchors(innerRect);
QQmlListReference list(rect, "states");
QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
+ QVERIFY(aChanges != nullptr);
rectPrivate->setState("right");
QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
@@ -907,11 +908,11 @@ void tst_qquickstates::anchorChangesRTL2()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges2.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
mirrorAnchors(innerRect);
rectPrivate->setState("right");
@@ -929,26 +930,26 @@ void tst_qquickstates::anchorChangesRTL3()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChanges3.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *innerRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("MyRect"));
- QVERIFY(innerRect != 0);
+ QVERIFY(innerRect != nullptr);
mirrorAnchors(innerRect);
QQuickItem *leftGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("LeftGuideline"));
- QVERIFY(leftGuideline != 0);
+ QVERIFY(leftGuideline != nullptr);
QQuickItem *bottomGuideline = qobject_cast<QQuickItem*>(rect->findChild<QQuickItem*>("BottomGuideline"));
- QVERIFY(bottomGuideline != 0);
+ QVERIFY(bottomGuideline != nullptr);
QQmlListReference list(rect, "states");
QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QQuickAnchorChanges *aChanges = qobject_cast<QQuickAnchorChanges*>(state->operationAt(0));
- QVERIFY(aChanges != 0);
+ QVERIFY(aChanges != nullptr);
rectPrivate->setState("reanchored");
QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
@@ -984,7 +985,7 @@ void tst_qquickstates::anchorChangesCrash()
QQmlComponent rectComponent(&engine, testFileUrl("anchorChangesCrash.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate::get(rect)->setState("reanchored");
@@ -1002,11 +1003,11 @@ void tst_qquickstates::anchorRewindBug()
QVERIFY(QTest::qWaitForWindowExposed(view));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(view->rootObject());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItem * column = rect->findChild<QQuickItem*>("column");
- QVERIFY(column != 0);
+ QVERIFY(column != nullptr);
QVERIFY(!QQuickItemPrivate::get(column)->heightValid);
QVERIFY(!QQuickItemPrivate::get(column)->widthValid);
QCOMPARE(column->height(), 200.0);
@@ -1036,11 +1037,11 @@ void tst_qquickstates::anchorRewindBug2()
QQmlComponent rectComponent(&engine, testFileUrl("anchorRewindBug2.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
- QVERIFY(mover != 0);
+ QVERIFY(mover != nullptr);
QCOMPARE(mover->y(), qreal(0.0));
QCOMPARE(mover->width(), qreal(50.0));
@@ -1062,7 +1063,7 @@ void tst_qquickstates::script()
{
QQmlComponent rectComponent(&engine, testFileUrl("script.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QCOMPARE(rect->color(),QColor("red"));
@@ -1080,7 +1081,7 @@ void tst_qquickstates::restoreEntryValues()
QQmlComponent rectComponent(&engine, testFileUrl("restoreEntryValues.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QCOMPARE(rect->color(),QColor("red"));
@@ -1097,15 +1098,15 @@ void tst_qquickstates::explicitChanges()
QQmlComponent rectComponent(&engine, testFileUrl("explicit.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQmlListReference list(rect, "states");
QQuickState *state = qobject_cast<QQuickState*>(list.at(0));
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QQuickPropertyChanges *changes = qobject_cast<QQuickPropertyChanges*>(rect->findChild<QQuickPropertyChanges*>("changes"));
- QVERIFY(changes != 0);
+ QVERIFY(changes != nullptr);
QVERIFY(changes->isExplicit());
QCOMPARE(rect->color(),QColor("red"));
@@ -1130,7 +1131,7 @@ void tst_qquickstates::propertyErrors()
QQmlEngine engine;
QQmlComponent rectComponent(&engine, testFileUrl("propertyErrors.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QCOMPARE(rect->color(),QColor("red"));
@@ -1145,7 +1146,7 @@ void tst_qquickstates::incorrectRestoreBug()
QQmlComponent rectComponent(&engine, testFileUrl("basicChanges.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QCOMPARE(rect->color(),QColor("red"));
@@ -1172,7 +1173,7 @@ void tst_qquickstates::autoStateAtStartupRestoreBug()
QQmlComponent component(&engine, testFileUrl("autoStateAtStartupRestoreBug.qml"));
QObject *obj = component.create();
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QCOMPARE(obj->property("test").toInt(), 3);
obj->setProperty("input", 2);
@@ -1188,7 +1189,7 @@ void tst_qquickstates::deletingChange()
QQmlComponent rectComponent(&engine, testFileUrl("deleting.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
rectPrivate->setState("blue");
QCOMPARE(rect->color(),QColor("blue"));
@@ -1199,11 +1200,11 @@ void tst_qquickstates::deletingChange()
QCOMPARE(rect->radius(),qreal(0));
QQuickPropertyChanges *pc = rect->findChild<QQuickPropertyChanges*>("pc1");
- QVERIFY(pc != 0);
+ QVERIFY(pc != nullptr);
delete pc;
QQuickState *state = rect->findChild<QQuickState*>();
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
qmlExecuteDeferred(state);
QCOMPARE(state->operationCount(), 1);
@@ -1220,11 +1221,11 @@ void tst_qquickstates::deletingState()
QQmlComponent rectComponent(&engine, testFileUrl("deletingState.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickStateGroup *sg = rect->findChild<QQuickStateGroup*>();
- QVERIFY(sg != 0);
- QVERIFY(sg->findState("blue") != 0);
+ QVERIFY(sg != nullptr);
+ QVERIFY(sg->findState("blue") != nullptr);
sg->setState("blue");
QCOMPARE(rect->color(),QColor("blue"));
@@ -1233,7 +1234,7 @@ void tst_qquickstates::deletingState()
QCOMPARE(rect->color(),QColor("red"));
QQuickState *state = rect->findChild<QQuickState*>();
- QVERIFY(state != 0);
+ QVERIFY(state != nullptr);
delete state;
QVERIFY(!sg->findState("blue"));
@@ -1251,7 +1252,7 @@ void tst_qquickstates::tempState()
QQmlComponent rectComponent(&engine, testFileUrl("legalTempState.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QTest::ignoreMessage(QtDebugMsg, "entering placed");
QTest::ignoreMessage(QtDebugMsg, "entering idle");
@@ -1265,7 +1266,7 @@ void tst_qquickstates::illegalTempState()
QQmlComponent rectComponent(&engine, testFileUrl("illegalTempState.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML StateGroup: Can't apply a state change as part of a state definition.");
rectPrivate->setState("placed");
@@ -1278,7 +1279,7 @@ void tst_qquickstates::nonExistantProperty()
QQmlComponent rectComponent(&engine, testFileUrl("nonExistantProp.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(rectComponent.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QTest::ignoreMessage(QtWarningMsg, fullDataPath("nonExistantProp.qml") + ":9:9: QML PropertyChanges: Cannot assign to non-existent property \"colr\"");
rectPrivate->setState("blue");
@@ -1291,10 +1292,10 @@ void tst_qquickstates::reset()
QQmlComponent c(&engine, testFileUrl("reset.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickImage *image = rect->findChild<QQuickImage*>();
- QVERIFY(image != 0);
+ QVERIFY(image != nullptr);
QCOMPARE(image->width(), qreal(40.));
QCOMPARE(image->height(), qreal(20.));
@@ -1325,7 +1326,7 @@ void tst_qquickstates::whenOrdering()
QQmlComponent c(&engine, testFileUrl("whenOrdering.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QCOMPARE(rectPrivate->state(), QLatin1String(""));
@@ -1348,13 +1349,13 @@ void tst_qquickstates::urlResolution()
QQmlComponent c(&engine, testFileUrl("urlResolution.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItem *myType = rect->findChild<QQuickItem*>("MyType");
QQuickImage *image1 = rect->findChild<QQuickImage*>("image1");
QQuickImage *image2 = rect->findChild<QQuickImage*>("image2");
QQuickImage *image3 = rect->findChild<QQuickImage*>("image3");
- QVERIFY(myType != 0 && image1 != 0 && image2 != 0 && image3 != 0);
+ QVERIFY(myType != nullptr && image1 != nullptr && image2 != nullptr && image3 != nullptr);
QQuickItemPrivate::get(myType)->setState("SetImageState");
QUrl resolved = testFileUrl("Implementation/images/qt-logo.png");
@@ -1371,7 +1372,7 @@ void tst_qquickstates::unnamedWhen()
QQmlComponent c(&engine, testFileUrl("unnamedWhen.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QCOMPARE(rectPrivate->state(), QLatin1String(""));
@@ -1390,7 +1391,7 @@ void tst_qquickstates::returnToBase()
QQmlComponent c(&engine, testFileUrl("returnToBase.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QCOMPARE(rectPrivate->state(), QLatin1String(""));
@@ -1410,7 +1411,7 @@ void tst_qquickstates::extendsBug()
QQmlComponent c(&engine, testFileUrl("extendsBug.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>("greenRect");
@@ -1425,30 +1426,30 @@ void tst_qquickstates::editProperties()
QQmlComponent c(&engine, testFileUrl("editProperties.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickStateGroup *stateGroup = rectPrivate->_states();
- QVERIFY(stateGroup != 0);
+ QVERIFY(stateGroup != nullptr);
qmlExecuteDeferred(stateGroup);
QQuickState *blueState = stateGroup->findState("blue");
- QVERIFY(blueState != 0);
+ QVERIFY(blueState != nullptr);
qmlExecuteDeferred(blueState);
QQuickPropertyChanges *propertyChangesBlue = qobject_cast<QQuickPropertyChanges*>(blueState->operationAt(0));
- QVERIFY(propertyChangesBlue != 0);
+ QVERIFY(propertyChangesBlue != nullptr);
QQuickState *greenState = stateGroup->findState("green");
- QVERIFY(greenState != 0);
+ QVERIFY(greenState != nullptr);
qmlExecuteDeferred(greenState);
QQuickPropertyChanges *propertyChangesGreen = qobject_cast<QQuickPropertyChanges*>(greenState->operationAt(0));
- QVERIFY(propertyChangesGreen != 0);
+ QVERIFY(propertyChangesGreen != nullptr);
QQuickRectangle *childRect = rect->findChild<QQuickRectangle*>("rect2");
- QVERIFY(childRect != 0);
+ QVERIFY(childRect != nullptr);
QCOMPARE(childRect->width(), qreal(402));
QVERIFY(QQmlPropertyPrivate::binding(QQmlProperty(childRect, "width")));
QCOMPARE(childRect->height(), qreal(200));
@@ -1553,7 +1554,7 @@ void tst_qquickstates::QTBUG_14830()
QQmlComponent c(&engine, testFileUrl("QTBUG-14830.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItem *item = rect->findChild<QQuickItem*>("area");
QCOMPARE(item->width(), qreal(170));
@@ -1566,7 +1567,7 @@ void tst_qquickstates::avoidFastForward()
//shouldn't fast forward if there isn't a transition
QQmlComponent c(&engine, testFileUrl("avoidFastForward.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
rectPrivate->setState("a");
@@ -1580,7 +1581,7 @@ void tst_qquickstates::revertListBug()
QQmlComponent c(&engine, testFileUrl("revertListBug.qml"));
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
- QVERIFY(rect != 0);
+ QVERIFY(rect != nullptr);
QQuickRectangle *rect1 = rect->findChild<QQuickRectangle*>("rect1");
QQuickRectangle *rect2 = rect->findChild<QQuickRectangle*>("rect2");
@@ -1621,7 +1622,7 @@ void tst_qquickstates::QTBUG_38492()
QQmlComponent rectComponent(&engine, testFileUrl("QTBUG-38492.qml"));
QQuickItem *item = qobject_cast<QQuickItem*>(rectComponent.create());
- QVERIFY(item != 0);
+ QVERIFY(item != nullptr);
QQuickItemPrivate::get(item)->setState("apply");
@@ -1654,6 +1655,17 @@ void tst_qquickstates::revertListMemoryLeak()
QVERIFY(bindingPtr->ref == 1);
}
+void tst_qquickstates::duplicateStateName()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, testFileUrl("duplicateStateName.qml"));
+ QTest::ignoreMessage(QtWarningMsg, fullDataPath("duplicateStateName.qml") + ":3:1: QML Rectangle: Found duplicate state name: state1");
+ QScopedPointer<QQuickItem> item(qobject_cast<QQuickItem *>(c.create()));
+ QVERIFY(!item.isNull());
+}
+
+
QTEST_MAIN(tst_qquickstates)
#include "tst_qquickstates.moc"
diff --git a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
index 045029c3b6..88b0e95e0a 100644
--- a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
+++ b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
@@ -44,7 +44,8 @@ public:
Bold = 0x01,
Underline = 0x02,
Italic = 0x04,
- Anchor = 0x08
+ Anchor = 0x08,
+ StrikeOut = 0x10
};
Format(int t, int s, int l)
: type(t), start(s), length(l) {}
@@ -92,6 +93,10 @@ void tst_qquickstyledtext::textOutput_data()
QTest::newRow("underline") << "<u>underline</u>" << "underline" << (FormatList() << Format(Format::Underline, 0, 9)) << false;
QTest::newRow("strong") << "<strong>strong</strong>" << "strong" << (FormatList() << Format(Format::Bold, 0, 6)) << false;
QTest::newRow("underline") << "<u>underline</u>" << "underline" << (FormatList() << Format(Format::Underline, 0, 9)) << false;
+ QTest::newRow("strike out s") << "<s>strike out</s>" << "strike out" << (FormatList() << Format(Format::StrikeOut, 0, 10)) << false;
+ QTest::newRow("strike out del") << "<del>strike out</del>" << "strike out" << (FormatList() << Format(Format::StrikeOut, 0, 10)) << false;
+ QTest::newRow("strike out not s") << "this is <s>not</s> a test" << "this is not a test" << (FormatList() << Format(Format::StrikeOut, 8, 3)) << false;
+ QTest::newRow("strike out not del") << "this is <del>not</del> a test" << "this is not a test" << (FormatList() << Format(Format::StrikeOut, 8, 3)) << false;
QTest::newRow("missing >") << "<b>text</b" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
QTest::newRow("missing b>") << "<b>text</" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
QTest::newRow("missing /b>") << "<b>text<" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
@@ -162,7 +167,7 @@ void tst_qquickstyledtext::textOutput()
QTextLayout layout;
QList<QQuickStyledTextImgTag*> imgTags;
bool fontSizeModified = false;
- QQuickStyledText::parse(input, layout, imgTags, QUrl(), 0, false, &fontSizeModified);
+ QQuickStyledText::parse(input, layout, imgTags, QUrl(), nullptr, false, &fontSizeModified);
QCOMPARE(layout.text(), output);
@@ -178,6 +183,7 @@ void tst_qquickstyledtext::textOutput()
QCOMPARE(layoutFormats.at(i).format.fontWeight(), int(QFont::Normal));
QVERIFY(layoutFormats.at(i).format.fontItalic() == bool(formats.at(i).type & Format::Italic));
QVERIFY(layoutFormats.at(i).format.fontUnderline() == bool(formats.at(i).type & Format::Underline));
+ QVERIFY(layoutFormats.at(i).format.fontStrikeOut() == bool(formats.at(i).type & Format::StrikeOut));
}
QCOMPARE(fontSizeModified, modifiesFontSize);
}
@@ -191,7 +197,7 @@ void tst_qquickstyledtext::anchors()
QTextLayout layout;
QList<QQuickStyledTextImgTag*> imgTags;
bool fontSizeModified = false;
- QQuickStyledText::parse(input, layout, imgTags, QUrl(), 0, false, &fontSizeModified);
+ QQuickStyledText::parse(input, layout, imgTags, QUrl(), nullptr, false, &fontSizeModified);
QCOMPARE(layout.text(), output);
@@ -229,11 +235,11 @@ void tst_qquickstyledtext::longString()
bool fontSizeModified = false;
QString input(9999999, QChar('.'));
- QQuickStyledText::parse(input, layout, imgTags, QUrl(), 0, false, &fontSizeModified);
+ QQuickStyledText::parse(input, layout, imgTags, QUrl(), nullptr, false, &fontSizeModified);
QCOMPARE(layout.text(), input);
input = QString(9999999, QChar('\t')); // whitespace
- QQuickStyledText::parse(input, layout, imgTags, QUrl(), 0, false, &fontSizeModified);
+ QQuickStyledText::parse(input, layout, imgTags, QUrl(), nullptr, false, &fontSizeModified);
QCOMPARE(layout.text(), QString(""));
}
diff --git a/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp b/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
index 136cfa9a80..071dcafc97 100644
--- a/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
+++ b/tests/auto/quick/qquicksystempalette/tst_qquicksystempalette.cpp
@@ -62,7 +62,7 @@ void tst_qquicksystempalette::activePalette()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickSystemPalette *object = qobject_cast<QQuickSystemPalette*>(component.create());
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
QPalette palette;
palette.setCurrentColorGroup(QPalette::Active);
@@ -91,7 +91,7 @@ void tst_qquicksystempalette::inactivePalette()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickSystemPalette *object = qobject_cast<QQuickSystemPalette*>(component.create());
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
QCOMPARE(object->colorGroup(), QQuickSystemPalette::Inactive);
QPalette palette;
@@ -121,7 +121,7 @@ void tst_qquicksystempalette::disabledPalette()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickSystemPalette *object = qobject_cast<QQuickSystemPalette*>(component.create());
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
QCOMPARE(object->colorGroup(), QQuickSystemPalette::Disabled);
QPalette palette;
@@ -152,7 +152,7 @@ void tst_qquicksystempalette::paletteChanged()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickSystemPalette *object = qobject_cast<QQuickSystemPalette*>(component.create());
- QVERIFY(object != 0);
+ QVERIFY(object != nullptr);
QPalette p;
p.setCurrentColorGroup(QPalette::Active);
diff --git a/tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml b/tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml
new file mode 100644
index 0000000000..e6cf9bf2a4
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/alternatingrowheightcolumnwidth.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property Component delegate: tableViewDelegate
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: column % 2 ? 40 : 30
+ implicitHeight: row % 2 ? 40 : 20
+ color: "lightgray"
+ border.width: 1
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/asyncloader.qml b/tests/auto/quick/qquicktableview/data/asyncloader.qml
new file mode 100644
index 0000000000..ba99430416
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/asyncloader.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ width: 640
+ height: 450
+
+ property alias loader: loader
+ property TableView tableView: loader.item ? loader.item.tableView : null
+ property string loaderSource: ""
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ source: Qt.resolvedUrl(loaderSource)
+ asynchronous: true
+ }
+}
diff --git a/tests/auto/quick/qquicktableview/data/asyncplain.qml b/tests/auto/quick/qquicktableview/data/asyncplain.qml
new file mode 100644
index 0000000000..df09d3e276
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/asyncplain.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import TestModel 0.1
+
+Item {
+ id: root
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property Loader loader: parent
+
+ property int statusWhenDelegate0_0Created: Loader.Null
+ property int statusWhenDelegate5_5Created: Loader.Null
+
+ property real tableViewWidthWhileBuilding: -1
+ property real tableViewHeightWhileBuilding: -1
+
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ model: TestModel {
+ rowCount: 100
+ columnCount: 100
+ }
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ implicitWidth: 100
+ implicitHeight: 50
+ color: "lightgray"
+ border.width: 1
+
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+
+ Component.onCompleted: {
+ if (row === 0 && column === 0) {
+ statusWhenDelegate0_0Created = loader.status
+ tableViewWidthWhileBuilding = tableView.width
+ tableViewHeightWhileBuilding = tableView.height
+ }
+ else if (row === 5 && column === 5)
+ statusWhenDelegate5_5Created = loader.status
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml b/tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml
new file mode 100644
index 0000000000..79a8e4351a
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/changemodelfromdelegate.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import TestModel 0.1
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property bool addRowFromDelegate: false
+
+ onAddRowFromDelegateChanged: {
+ if (!addRowFromDelegate)
+ return;
+ tableModel.addRow(0);
+ tableView.forceLayout();
+ }
+
+ TestModel {
+ id: tableModel
+ rowCount: 1
+ columnCount: 4
+ }
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ clip: true
+ model: tableModel
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: 100
+ implicitHeight: 100
+ color: "lightgray"
+ border.width: 1
+
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+
+ Component.onCompleted: {
+ if (!addRowFromDelegate)
+ return;
+ addRowFromDelegate = false;
+ tableModel.addRow(0);
+ }
+ }
+ }
+
+}
+
diff --git a/tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml b/tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml
new file mode 100644
index 0000000000..de404be63d
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/changemodelordelegateduringupdate.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property bool changeDelegate: false
+ property bool changeModel: false
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ clip: true
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ implicitWidth: 100
+ implicitHeight: 100
+ color: "lightgray"
+ border.width: 1
+
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+
+ Component.onCompleted: {
+ if (changeDelegate)
+ TableView.view.delegate = null
+ if (changeModel)
+ TableView.view.model = null
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml b/tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml
new file mode 100644
index 0000000000..0550f20bac
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/checkmodelpropertyrevision.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.12
+
+Item {
+ id: root
+ width: 640
+ height: 480
+
+ property alias tableView: tableView
+
+ property int row: 42
+ property int column: 42
+
+ property int resolvedDelegateRow: 0
+ property int resolvedDelegateColumn: 0
+
+ TableView {
+ id: tableView
+ // Dummy tableView, to let the auto test follow the
+ // same pattern for loading qml files as other tests.
+ }
+
+ Item {
+ width: 100
+ height: parent.height;
+ Repeater {
+ model: 1
+ delegate: Component {
+ Rectangle {
+ color: "blue"
+ height: 100
+ width: 100
+ Component.onCompleted: {
+ // row and column should be resolved to be the ones
+ // found in the root item, and not in the delegate
+ // items context. The context properties are revisioned,
+ // and require that the QQmlDelegateModel has an import
+ // version set (which is not the case when using a
+ // Repeater, only when using a TableView).
+ resolvedDelegateRow = row
+ resolvedDelegateColumn = column
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml b/tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml
new file mode 100644
index 0000000000..bef0df2501
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/checkrowandcolumnnotchanged.qml
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import Qt.labs.qmlmodels 1.0
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ delegate: DelegateChooser {
+ DelegateChoice {
+ row: 0
+ column: 0
+ delegate: maskDelegate
+ }
+ DelegateChoice {
+ row: 1
+ column: 1
+ delegate: maskDelegate
+ }
+ DelegateChoice {
+ delegate: tableViewDelegate
+ }
+ }
+ }
+
+ Component {
+ // Add this mask delegate, to force QQmlTableInstanceModel to
+ // reuse the precise cells that we want to swap in the test
+ id: maskDelegate
+ Rectangle {
+ implicitWidth: 100
+ implicitHeight: 50
+ color: "green"
+ }
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ implicitWidth: 100
+ implicitHeight: 50
+ Text {
+ anchors.fill: parent
+ text: column + "," + row
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/contentwidthheight.qml b/tests/auto/quick/qquicktableview/data/contentwidthheight.qml
new file mode 100644
index 0000000000..6b15e8dd21
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/contentwidthheight.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property Component delegate: tableViewDelegate
+
+ TableView {
+ id: tableView
+ width: 500
+ height: 500
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ leftMargin: 10
+ rightMargin: 10
+ topMargin: 10
+ bottomMargin: 10
+ columnWidthProvider: function(column) { return column < 20 ? 100 : 200 }
+ rowHeightProvider: function(row) { return row < 20 ? 100 : 200 }
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ color: "lightgray"
+ border.width: 1
+ Text {
+ anchors.centerIn: parent
+ text: column
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/countingtableview.qml b/tests/auto/quick/qquicktableview/data/countingtableview.qml
new file mode 100644
index 0000000000..ecd4ca3cc7
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/countingtableview.qml
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ id: root
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ // currentDelegateCount is the number of currently visible items
+ property int currentDelegateCount: 0
+ // maxDelegateCount is the largest number of items that has ever been visible at the same time
+ property int maxDelegateCount: 0
+ // delegatesCreatedCount is the number of items created during the lifetime of the test
+ property int delegatesCreatedCount: 0
+
+ property real delegateWidth: 100
+ property real delegateHeight: 50
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: delegateWidth
+ implicitHeight: delegateHeight
+ color: "lightgray"
+ border.width: 1
+
+ property int pooledCount: 0
+ property int reusedCount: 0
+ TableView.onPooled: pooledCount++;
+ TableView.onReused: reusedCount++;
+
+ Text {
+ anchors.centerIn: parent
+ text: column
+ }
+ Component.onCompleted: {
+ delegatesCreatedCount++;
+ currentDelegateCount++;
+ maxDelegateCount = Math.max(maxDelegateCount, currentDelegateCount);
+ }
+ Component.onDestruction: {
+ currentDelegateCount--;
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/delegatewithanchors.qml b/tests/auto/quick/qquicktableview/data/delegatewithanchors.qml
new file mode 100644
index 0000000000..0b549f09a4
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/delegatewithanchors.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ anchors.fill: parent
+ implicitWidth: 100
+ implicitHeight: 100
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/forcelayout.qml b/tests/auto/quick/qquicktableview/data/forcelayout.qml
new file mode 100644
index 0000000000..f03dc2f25b
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/forcelayout.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property real columnWidths: 80
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+
+ columnWidthProvider: function(c) { return columnWidths; }
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ color: "lightgray"
+ border.width: 1
+ implicitHeight: 100
+
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml b/tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml
new file mode 100644
index 0000000000..b11cb1476c
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/hiderowsandcolumns.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property var rowsToHide
+ property var columnsToHide
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ columnWidthProvider: function(column) {
+ if (columnsToHide.includes(column))
+ return 0;
+ }
+ rowHeightProvider: function(row) {
+ if (rowsToHide.includes(row))
+ return 0;
+ }
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ color: "lightgray"
+ border.width: 1
+ implicitWidth: 50
+ implicitHeight: 50
+ Text {
+ anchors.centerIn: parent
+ text: column + "," + row
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/plaintableview.qml b/tests/auto/quick/qquicktableview/data/plaintableview.qml
new file mode 100644
index 0000000000..90271eda71
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/plaintableview.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property real delegateWidth: 100
+ property real delegateHeight: 50
+ property Component delegate: tableViewDelegate
+ property bool delegateParentSetBeforeCompleted: false
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: delegateWidth
+ implicitHeight: delegateHeight
+ color: "lightgray"
+ border.width: 1
+
+ property string modelDataBinding: modelData
+
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+
+ Component.onCompleted: {
+ delegateParentSetBeforeCompleted = parent != null;
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml b/tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml
new file mode 100644
index 0000000000..38fca2c5cb
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/qqmllistpropertymodel.qml
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ id: root
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ }
+
+ Item {
+ Repeater {
+ model: 100
+ Item { property string someCustomProperty: index }
+ }
+ Component.onCompleted: tableView.model = children
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: 100
+ implicitHeight: 50
+ color: "lightgray"
+ border.width: 1
+
+ Text {
+ anchors.centerIn: parent
+ text: column
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/setcontentpos.qml b/tests/auto/quick/qquicktableview/data/setcontentpos.qml
new file mode 100644
index 0000000000..fa040d3959
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/setcontentpos.qml
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 400
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ contentX: (contentWidth - width) / 2;
+ contentY: (contentHeight - height) / 2;
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ implicitWidth: 100
+ implicitHeight: 100
+ color: "lightgray"
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml b/tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml
new file mode 100644
index 0000000000..f4a3094dd2
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/tableviewdefaultspacing.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ color: "lightgray"
+ border.width: 1
+ implicitWidth: 15
+ implicitHeight: 10
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/tableviewfocus.qml b/tests/auto/quick/qquicktableview/data/tableviewfocus.qml
new file mode 100644
index 0000000000..c388e2c8de
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/tableviewfocus.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ clip: true
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Item {
+ id: delegate
+ implicitWidth: 100
+ implicitHeight: 50
+ focus: true
+
+ property alias delegateRoot: delegate
+ property alias delegateChild: textInput
+
+ TextInput {
+ id: textInput
+ width: parent.width
+ height: parent.height
+ text: "TextInput"
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml b/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml
new file mode 100644
index 0000000000..425b950fce
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/tableviewimplicitsize.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ color: "lightgray"
+ border.width: 1
+ implicitWidth: 90
+ implicitHeight: 60
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml b/tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml
new file mode 100644
index 0000000000..847500d71f
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/usechooserwithoutdefault.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+import Qt.labs.qmlmodels 1.0
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ delegate: DelegateChooser {
+ DelegateChoice {
+ row: 0
+ delegate: Item {
+ implicitWidth: 100
+ implicitHeight: 100
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml b/tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml
new file mode 100644
index 0000000000..1e35d65bcd
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/usefaultyrowcolumnprovider.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property Component delegate: tableViewDelegate
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ columnWidthProvider: function(column) { return "notAValidValue" }
+ rowHeightProvider: function(row) { return "notAValidValue" }
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ color: "lightgray"
+ border.width: 1
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml b/tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml
new file mode 100644
index 0000000000..e9f01b6abf
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/userowcolumnprovider.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property Component delegate: tableViewDelegate
+ property bool returnNegativeColumnWidth: false
+ property bool returnNegativeRowHeight: false
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ columnWidthProvider: function(column) {
+ if (returnNegativeColumnWidth)
+ return -1
+ return column + 10
+ }
+ rowHeightProvider: function(row) {
+ if (returnNegativeRowHeight)
+ return -1
+ return row + 10
+ }
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: 20
+ implicitHeight: 20
+ color: "lightgray"
+ border.width: 1
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/qquicktableview.pro b/tests/auto/quick/qquicktableview/qquicktableview.pro
new file mode 100644
index 0000000000..cf831ed5b5
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/qquicktableview.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+QT += qmltest
+TARGET = tst_qquicktableview
+macos:CONFIG -= app_bundle
+
+HEADERS += testmodel.h
+SOURCES += tst_qquicktableview.cpp
+
+include (../../shared/util.pri)
+include (../shared/util.pri)
+
+TESTDATA = data/*
+
+QT += core-private gui-private qml-private quick-private testlib
+
diff --git a/tests/auto/quick/qquicktableview/testmodel.h b/tests/auto/quick/qquicktableview/testmodel.h
new file mode 100644
index 0000000000..50f434019e
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/testmodel.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtCore>
+#include <QtGui/QStandardItemModel>
+
+class TestModel : public QAbstractTableModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged)
+ Q_PROPERTY(int columnCount READ columnCount WRITE setColumnCount NOTIFY columnCountChanged)
+
+public:
+ TestModel(QObject *parent = nullptr)
+ : QAbstractTableModel(parent)
+ {}
+
+ TestModel(int rows, int columns, QObject *parent = nullptr)
+ : QAbstractTableModel(parent)
+ , m_rows(rows)
+ , m_columns(columns)
+ {}
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override { return m_rows; }
+ void setRowCount(int count) { beginResetModel(); m_rows = count; emit rowCountChanged(); endResetModel(); }
+
+ int columnCount(const QModelIndex & = QModelIndex()) const override { return m_columns; }
+ void setColumnCount(int count) { beginResetModel(); m_columns = count; emit columnCountChanged(); endResetModel(); }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ if (!index.isValid() || role != Qt::DisplayRole)
+ return QVariant();
+
+ int serializedIndex = index.row() + (index.column() * m_columns);
+ if (modelData.contains(serializedIndex))
+ return modelData.value(serializedIndex);
+ return QStringLiteral("%1").arg(index.row());
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return { {Qt::DisplayRole, "display"} };
+ }
+
+ Q_INVOKABLE void setModelData(const QPoint &cell, const QSize &span, const QString &string)
+ {
+ for (int c = 0; c < span.width(); ++c) {
+ for (int r = 0; r < span.height(); ++r) {
+ const int changedRow = cell.y() + r;
+ const int changedColumn = cell.x() + c;
+ const int serializedIndex = changedRow + (changedColumn * m_rows);
+ modelData.insert(serializedIndex, string);
+ }
+ }
+
+ const auto topLeftIndex = createIndex(cell.y(), cell.x(), nullptr);
+ const auto bottomRightIndex = createIndex(cell.y() + span.height() - 1, cell.x() + span.width() - 1, nullptr);
+ emit dataChanged(topLeftIndex, bottomRightIndex);
+ }
+
+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override
+ {
+ if (row < 0 || count <= 0)
+ return false;
+
+ beginInsertRows(parent, row, row + count - 1);
+ m_rows += count;
+ endInsertRows();
+ return true;
+ }
+
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override
+ {
+ if (!checkIndex(createIndex(row, 0)) || !checkIndex(createIndex(row + count - 1, 0)))
+ return false;
+
+ beginRemoveRows(parent, row, row + count - 1);
+ m_rows -= count;
+ endRemoveRows();
+ return true;
+ }
+
+ bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override
+ {
+ if (column < 0 || count <= 0)
+ return false;
+
+ beginInsertColumns(parent, column, column + count - 1);
+ m_columns += count;
+ endInsertColumns();
+ return true;
+ }
+
+ bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override
+ {
+ if (!checkIndex(createIndex(0, column)) || !checkIndex(createIndex(0, column + count - 1)))
+ return false;
+
+ beginRemoveColumns(parent, column, column + count - 1);
+ m_columns -= count;
+ endRemoveColumns();
+ return true;
+ }
+
+ void swapRows(int row1, int row2)
+ {
+ layoutAboutToBeChanged();
+ Q_ASSERT(modelData.contains(row1));
+ Q_ASSERT(modelData.contains(row2));
+ const QString tmp = modelData[row1];
+ modelData[row1] = modelData[row2];
+ modelData[row2] = tmp;
+ layoutChanged();
+ }
+
+ void clear() {
+ beginResetModel();
+ m_rows = 0;
+ m_columns = 0;
+ modelData.clear();
+ endResetModel();
+ }
+
+ Q_INVOKABLE void addRow(int row)
+ {
+ insertRow(row, QModelIndex());
+ }
+
+signals:
+ void rowCountChanged();
+ void columnCountChanged();
+
+private:
+ int m_rows = 0;
+ int m_columns = 0;
+ QHash<int, QString> modelData;
+};
+
+#define TestModelAsVariant(...) QVariant::fromValue(QSharedPointer<TestModel>(new TestModel(__VA_ARGS__)))
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
new file mode 100644
index 0000000000..60d48bb59f
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -0,0 +1,2157 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtQuickTest/quicktest.h>
+
+#include <QtQuick/qquickview.h>
+#include <QtQuick/private/qquicktableview_p.h>
+#include <QtQuick/private/qquicktableview_p_p.h>
+#include <QtQuick/private/qquickloader_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlexpression.h>
+#include <QtQml/qqmlincubator.h>
+#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <QtQml/private/qqmllistmodel_p.h>
+
+#include "testmodel.h"
+
+#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
+#include "../shared/visualtestutil.h"
+
+using namespace QQuickViewTestUtil;
+using namespace QQuickVisualTestUtil;
+
+static const char* kTableViewPropName = "tableView";
+static const char* kDelegateObjectName = "tableViewDelegate";
+static const char *kDelegatesCreatedCountProp = "delegatesCreatedCount";
+static const char *kModelDataBindingProp = "modelDataBinding";
+
+Q_DECLARE_METATYPE(QMarginsF);
+
+#define DECLARE_TABLEVIEW_VARIABLES \
+ auto tableView = view->rootObject()->property(kTableViewPropName).value<QQuickTableView *>(); \
+ QVERIFY(tableView); \
+ auto tableViewPrivate = QQuickTableViewPrivate::get(tableView); \
+ Q_UNUSED(tableViewPrivate)
+
+#define LOAD_TABLEVIEW(fileName) \
+ view->setSource(testFileUrl(fileName)); \
+ view->show(); \
+ QVERIFY(QTest::qWaitForWindowActive(view)); \
+ DECLARE_TABLEVIEW_VARIABLES
+
+#define LOAD_TABLEVIEW_ASYNC(fileName) \
+ view->setSource(testFileUrl("asyncloader.qml")); \
+ view->show(); \
+ QVERIFY(QTest::qWaitForWindowActive(view)); \
+ auto loader = view->rootObject()->property("loader").value<QQuickLoader *>(); \
+ loader->setSource(QUrl::fromLocalFile("data/" fileName)); \
+ QTRY_VERIFY(loader->item()); \
+ QCOMPARE(loader->status(), QQuickLoader::Status::Ready); \
+ DECLARE_TABLEVIEW_VARIABLES
+
+#define WAIT_UNTIL_POLISHED \
+ QVERIFY(QQuickTest::qIsPolishScheduled(tableView)); \
+ QVERIFY(QQuickTest::qWaitForItemPolished(tableView))
+
+class tst_QQuickTableView : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_QQuickTableView();
+
+ QQuickTableViewAttached *getAttachedObject(const QObject *object) const;
+ QPoint getContextRowAndColumn(const QQuickItem *item) const;
+
+private:
+ QQuickView *view = nullptr;
+
+private slots:
+ void initTestCase() override;
+ void cleanupTestCase();
+
+ void setAndGetModel_data();
+ void setAndGetModel();
+ void emptyModel_data();
+ void emptyModel();
+ void checkPreload_data();
+ void checkPreload();
+ void checkZeroSizedDelegate();
+ void checkImplicitSizeDelegate();
+ void checkColumnWidthWithoutProvider();
+ void checkDelegateWithAnchors();
+ void checkColumnWidthProvider();
+ void checkColumnWidthProviderInvalidReturnValues();
+ void checkColumnWidthProviderNegativeReturnValue();
+ void checkColumnWidthProviderNotCallable();
+ void checkRowHeightWithoutProvider();
+ void checkRowHeightProvider();
+ void checkRowHeightProviderInvalidReturnValues();
+ void checkRowHeightProviderNegativeReturnValue();
+ void checkRowHeightProviderNotCallable();
+ void checkForceLayoutFunction();
+ void checkContentWidthAndHeight();
+ void checkPageFlicking();
+ void checkExplicitContentWidthAndHeight();
+ void checkContentXY();
+ void noDelegate();
+ void changeDelegateDuringUpdate();
+ void changeModelDuringUpdate();
+ void countDelegateItems_data();
+ void countDelegateItems();
+ void checkLayoutOfEqualSizedDelegateItems_data();
+ void checkLayoutOfEqualSizedDelegateItems();
+ void checkFocusRemoved_data();
+ void checkFocusRemoved();
+ void fillTableViewButNothingMore_data();
+ void fillTableViewButNothingMore();
+ void checkInitialAttachedProperties_data();
+ void checkInitialAttachedProperties();
+ void checkSpacingValues();
+ void checkDelegateParent();
+ void flick_data();
+ void flick();
+ void flickOvershoot_data();
+ void flickOvershoot();
+ void checkRowColumnCount();
+ void modelSignals();
+ void checkModelSignalsUpdateLayout();
+ void dataChangedSignal();
+ void checkThatPoolIsDrainedWhenReuseIsFalse();
+ void checkIfDelegatesAreReused_data();
+ void checkIfDelegatesAreReused();
+ void checkIfDelegatesAreReusedAsymmetricTableSize();
+ void checkContextProperties_data();
+ void checkContextProperties();
+ void checkContextPropertiesQQmlListProperyModel_data();
+ void checkContextPropertiesQQmlListProperyModel();
+ void checkRowAndColumnChangedButNotIndex();
+ void checkChangingModelFromDelegate();
+ void checkRebuildViewportOnly();
+ void useDelegateChooserWithoutDefault();
+ void checkTableviewInsideAsyncLoader();
+ void hideRowsAndColumns_data();
+ void hideRowsAndColumns();
+ void checkThatRevisionedPropertiesCannotBeUsedInOldImports();
+};
+
+tst_QQuickTableView::tst_QQuickTableView()
+{
+}
+
+void tst_QQuickTableView::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ qmlRegisterType<TestModel>("TestModel", 0, 1, "TestModel");
+ view = createView();
+}
+
+void tst_QQuickTableView::cleanupTestCase()
+{
+ delete view;
+}
+
+QQuickTableViewAttached *tst_QQuickTableView::getAttachedObject(const QObject *object) const
+{
+ QObject *attachedObject = qmlAttachedPropertiesObject<QQuickTableView>(object);
+ return static_cast<QQuickTableViewAttached *>(attachedObject);
+}
+
+QPoint tst_QQuickTableView::getContextRowAndColumn(const QQuickItem *item) const
+{
+ const auto context = qmlContext(item);
+ const int row = context->contextProperty("row").toInt();
+ const int column = context->contextProperty("column").toInt();
+ return QPoint(column, row);
+}
+
+void tst_QQuickTableView::setAndGetModel_data()
+{
+ QTest::addColumn<QVariant>("model");
+
+ QTest::newRow("QAIM 1x1") << TestModelAsVariant(1, 1);
+ QTest::newRow("Number model 1") << QVariant::fromValue(1);
+ QTest::newRow("QStringList 1") << QVariant::fromValue(QStringList() << "one");
+}
+
+void tst_QQuickTableView::setAndGetModel()
+{
+ // Test that we can set and get different kind of models
+ QFETCH(QVariant, model);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+ QCOMPARE(model, tableView->model());
+}
+
+void tst_QQuickTableView::emptyModel_data()
+{
+ QTest::addColumn<QVariant>("model");
+
+ QTest::newRow("QAIM") << TestModelAsVariant(0, 0);
+ QTest::newRow("Number model") << QVariant::fromValue(0);
+ QTest::newRow("QStringList") << QVariant::fromValue(QStringList());
+}
+
+void tst_QQuickTableView::emptyModel()
+{
+ // Check that if we assign an empty model to
+ // TableView, no delegate items will be created.
+ QFETCH(QVariant, model);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableViewPrivate->loadedItems.count(), 0);
+}
+
+void tst_QQuickTableView::checkPreload_data()
+{
+ QTest::addColumn<bool>("reuseItems");
+
+ QTest::newRow("reuse") << true;
+ QTest::newRow("not reuse") << false;
+}
+
+void tst_QQuickTableView::checkPreload()
+{
+ // Check that the reuse pool is filled up with one extra row and
+ // column (pluss corner) after rebuilding the table, but only if we reuse items.
+ QFETCH(bool, reuseItems);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+ tableView->setReuseItems(reuseItems);
+
+ WAIT_UNTIL_POLISHED;
+
+ if (reuseItems) {
+ const int rowCount = tableViewPrivate->loadedRows.count();
+ const int columnCount = tableViewPrivate->loadedColumns.count();
+ const int expectedPoolSize = rowCount + columnCount + 1;
+ QCOMPARE(tableViewPrivate->tableModel->poolSize(), expectedPoolSize);
+ } else {
+ QCOMPARE(tableViewPrivate->tableModel->poolSize(), 0);
+ }
+}
+
+void tst_QQuickTableView::checkZeroSizedDelegate()
+{
+ // Check that if we assign a delegate with empty width and height, we
+ // fall back to use kDefaultColumnWidth and kDefaultRowHeight as
+ // column/row sizes.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ view->rootObject()->setProperty("delegateWidth", 0);
+ view->rootObject()->setProperty("delegateHeight", 0);
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicit"));
+
+ WAIT_UNTIL_POLISHED;
+
+ auto items = tableViewPrivate->loadedItems;
+ QVERIFY(!items.isEmpty());
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ auto item = fxItem->item;
+ QCOMPARE(item->width(), kDefaultColumnWidth);
+ QCOMPARE(item->height(), kDefaultRowHeight);
+ }
+}
+
+void tst_QQuickTableView::checkImplicitSizeDelegate()
+{
+ // Check that we can set the size of delegate items using
+ // implicit width/height, instead of forcing the user to
+ // create an attached object by using implicitWidth/Height.
+ LOAD_TABLEVIEW("tableviewimplicitsize.qml");
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto items = tableViewPrivate->loadedItems;
+ QVERIFY(!items.isEmpty());
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ auto item = fxItem->item;
+ QCOMPARE(item->width(), 90);
+ QCOMPARE(item->height(), 60);
+ }
+}
+
+void tst_QQuickTableView::checkColumnWidthWithoutProvider()
+{
+ // Checks that a function isn't assigned to the columnWidthProvider property
+ // and that the column width is then equal to sizeHintForColumn.
+ LOAD_TABLEVIEW("alternatingrowheightcolumnwidth.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+ QVERIFY(tableView->columnWidthProvider().isUndefined());
+
+ WAIT_UNTIL_POLISHED;
+
+ for (const int column : tableViewPrivate->loadedColumns.keys()) {
+ const qreal expectedColumnWidth = tableViewPrivate->sizeHintForColumn(column);
+ for (const int row : tableViewPrivate->loadedRows.keys()) {
+ const auto item = tableViewPrivate->loadedTableItem(QPoint(column, row))->item;
+ QCOMPARE(item->width(), expectedColumnWidth);
+ }
+ }
+}
+
+void tst_QQuickTableView::checkDelegateWithAnchors()
+{
+ // Checks that we issue a warning if the delegate has anchors
+ LOAD_TABLEVIEW("delegatewithanchors.qml");
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*anchors"));
+
+ auto model = TestModelAsVariant(1, 1);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+}
+
+void tst_QQuickTableView::checkColumnWidthProvider()
+{
+ // Check that you can assign a function to the columnWidthProvider property, and
+ // that it's used to control (and override) the width of the columns.
+ LOAD_TABLEVIEW("userowcolumnprovider.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+ QVERIFY(tableView->columnWidthProvider().isCallable());
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ // expectedWidth mirrors the expected return value of the assigned javascript function
+ qreal expectedWidth = fxItem->cell.x() + 10;
+ QCOMPARE(fxItem->item->width(), expectedWidth);
+ }
+}
+
+void tst_QQuickTableView::checkColumnWidthProviderInvalidReturnValues()
+{
+ // Check that we fall back to use default columns widths, if you
+ // assign a function to columnWidthProvider that returns invalid values.
+ LOAD_TABLEVIEW("usefaultyrowcolumnprovider.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicitHeight.*zero"));
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->width(), kDefaultColumnWidth);
+}
+
+void tst_QQuickTableView::checkColumnWidthProviderNegativeReturnValue()
+{
+ // Check that we fall back to use the implicit width of the delegate
+ // items if the columnWidthProvider return a negative number.
+ LOAD_TABLEVIEW("userowcolumnprovider.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+ view->rootObject()->setProperty("returnNegativeColumnWidth", true);
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->width(), 20);
+}
+
+void tst_QQuickTableView::checkColumnWidthProviderNotCallable()
+{
+ // Check that we fall back to use default columns widths, if you
+ // assign something to columnWidthProvider that is not callable.
+ LOAD_TABLEVIEW("usefaultyrowcolumnprovider.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+ tableView->setRowHeightProvider(QJSValue());
+ tableView->setColumnWidthProvider(QJSValue(10));
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".Provider.*function"));
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->width(), kDefaultColumnWidth);
+}
+
+void tst_QQuickTableView::checkRowHeightWithoutProvider()
+{
+ // Checks that a function isn't assigned to the rowHeightProvider property
+ // and that the row height is then equal to sizeHintForRow.
+ LOAD_TABLEVIEW("alternatingrowheightcolumnwidth.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+ QVERIFY(tableView->rowHeightProvider().isUndefined());
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ for (const int row : tableViewPrivate->loadedRows.keys()) {
+ const qreal expectedRowHeight = tableViewPrivate->sizeHintForRow(row);
+ for (const int column : tableViewPrivate->loadedColumns.keys()) {
+ const auto item = tableViewPrivate->loadedTableItem(QPoint(column, row))->item;
+ QCOMPARE(item->height(), expectedRowHeight);
+ }
+ }
+}
+
+void tst_QQuickTableView::checkRowHeightProvider()
+{
+ // Check that you can assign a function to the columnWidthProvider property, and
+ // that it's used to control (and override) the width of the columns.
+ LOAD_TABLEVIEW("userowcolumnprovider.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+ QVERIFY(tableView->rowHeightProvider().isCallable());
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ // expectedWidth mirrors the expected return value of the assigned javascript function
+ qreal expectedHeight = fxItem->cell.y() + 10;
+ QCOMPARE(fxItem->item->height(), expectedHeight);
+ }
+}
+
+void tst_QQuickTableView::checkRowHeightProviderInvalidReturnValues()
+{
+ // Check that we fall back to use default row heights, if you
+ // assign a function to rowHeightProvider that returns invalid values.
+ LOAD_TABLEVIEW("usefaultyrowcolumnprovider.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicitHeight.*zero"));
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->height(), kDefaultRowHeight);
+}
+
+void tst_QQuickTableView::checkRowHeightProviderNegativeReturnValue()
+{
+ // Check that we fall back to use the implicit height of the delegate
+ // items if the rowHeightProvider return a negative number.
+ LOAD_TABLEVIEW("userowcolumnprovider.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+ view->rootObject()->setProperty("returnNegativeRowHeight", true);
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->height(), 20);
+}
+
+void tst_QQuickTableView::checkRowHeightProviderNotCallable()
+{
+ // Check that we fall back to use default row heights, if you
+ // assign something to rowHeightProvider that is not callable.
+ LOAD_TABLEVIEW("usefaultyrowcolumnprovider.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+
+ tableView->setColumnWidthProvider(QJSValue());
+ tableView->setRowHeightProvider(QJSValue(10));
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*Provider.*function"));
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->height(), kDefaultRowHeight);
+}
+
+void tst_QQuickTableView::checkForceLayoutFunction()
+{
+ // When we set the 'columnWidths' property in the test file, the
+ // columnWidthProvider should return other values than it did during
+ // start-up. Check that this takes effect after a call to the 'forceLayout()' function.
+ LOAD_TABLEVIEW("forcelayout.qml");
+
+ const char *propertyName = "columnWidths";
+ auto model = TestModelAsVariant(10, 10);
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Check that the initial column widths are as specified in the QML file
+ const qreal initialColumnWidth = view->rootObject()->property(propertyName).toReal();
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->width(), initialColumnWidth);
+
+ // Change the return value from the columnWidthProvider to something else
+ const qreal newColumnWidth = 100;
+ view->rootObject()->setProperty(propertyName, newColumnWidth);
+ tableView->forceLayout();
+ // We don't have to polish; The re-layout happens immediately
+
+ for (auto fxItem : tableViewPrivate->loadedItems)
+ QCOMPARE(fxItem->item->width(), newColumnWidth);
+}
+
+void tst_QQuickTableView::checkContentWidthAndHeight()
+{
+ // Check that contentWidth/Height reports the correct size of the the
+ // table, based on knowledge of the rows and columns that has been loaded.
+ LOAD_TABLEVIEW("contentwidthheight.qml");
+
+ // Vertical and horizontal properties should be mirrored, so we only have
+ // to do the calculations once, and use them for both axis, below.
+ QCOMPARE(tableView->width(), tableView->height());
+ QCOMPARE(tableView->rowSpacing(), tableView->columnSpacing());
+
+ const int tableSize = 100;
+ const int cellSizeSmall = 100;
+ const int cellSizeLarge = 200;
+ const int spacing = 1;
+ const int smallCellCount = 20;
+ const int largeCellCount = tableSize - smallCellCount;
+ const qreal accumulatedSpacing = ((tableSize - 1) * spacing);
+ auto model = TestModelAsVariant(tableSize, tableSize);
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ const qreal expectedSizeInit = (tableSize * cellSizeSmall) + ((tableSize - 1) * spacing);
+ QCOMPARE(tableView->contentWidth(), expectedSizeInit);
+ QCOMPARE(tableView->contentHeight(), expectedSizeInit);
+ QCOMPARE(tableViewPrivate->averageEdgeSize.width(), cellSizeSmall);
+ QCOMPARE(tableViewPrivate->averageEdgeSize.height(), cellSizeSmall);
+
+ // Flick in 5 more rows and columns, but not so far that we start loading in
+ // the ones that are bigger. Loading in more rows and columns of the same
+ // size as the initial ones should not change the first prediction.
+ qreal flickTo = ((cellSizeSmall + spacing) * 5);
+ tableView->setContentX(flickTo);
+ tableView->setContentY(flickTo);
+
+ QCOMPARE(tableView->contentWidth(), expectedSizeInit);
+ QCOMPARE(tableView->contentHeight(), expectedSizeInit);
+ QCOMPARE(tableViewPrivate->averageEdgeSize.width(), cellSizeSmall);
+ QCOMPARE(tableViewPrivate->averageEdgeSize.height(), cellSizeSmall);
+
+ // Flick to row and column 20 (smallCellCount), since there the row and
+ // column sizes increases with 100. Check that TableView then adjusts
+ // contentWidth and contentHeight accordingly.
+ flickTo = ((cellSizeSmall + spacing) * smallCellCount) - spacing;
+ tableView->setContentX(flickTo);
+ tableView->setContentY(flickTo);
+
+ // Since we move the viewport more than a page, tableview
+ // will jump to the new position and do a rebuild.
+ QVERIFY(tableViewPrivate->polishScheduled);
+ QVERIFY(tableViewPrivate->rebuildScheduled);
+ WAIT_UNTIL_POLISHED;
+
+ // Check that the average cell size is now matching the
+ // large cells since they fill up the whole view.
+ QCOMPARE(tableViewPrivate->averageEdgeSize.width(), cellSizeLarge);
+ QCOMPARE(tableViewPrivate->averageEdgeSize.height(), cellSizeLarge);
+
+ const int largeSizeCellCountInView = qCeil(tableView->width() / cellSizeLarge);
+ const int columnCount = smallCellCount + largeSizeCellCountInView;
+ QCOMPARE(tableViewPrivate->leftColumn(), smallCellCount);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+
+ const qreal firstHalfLength = smallCellCount * cellSizeSmall;
+ const qreal secondHalfOneScreenLength = largeSizeCellCountInView * cellSizeLarge;
+ const qreal lengthAfterFlick = firstHalfLength + secondHalfOneScreenLength;
+
+ // Check that loadedTableOuterRect has been calculated correct thus far
+ const qreal spacingAfterFlick = (smallCellCount + largeSizeCellCountInView - 1) * spacing;
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.left(), flickTo + spacing);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.right(), lengthAfterFlick + spacingAfterFlick);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.top(), flickTo + spacing);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.bottom(), lengthAfterFlick + spacingAfterFlick);
+
+ // At this point, we should have the exact content width/height set, because
+ // TableView knows where the large cells start in the viewport, and how many
+ // columns that remain in the model. It will assume that the rest of the the
+ // columns have the same average size as the ones currently inside the viewport.
+ const qreal expectedContentSize = (smallCellCount * cellSizeSmall) + (largeCellCount * cellSizeLarge) + accumulatedSpacing;
+ QCOMPARE(tableView->contentWidth(), expectedContentSize);
+ QCOMPARE(tableView->contentHeight(), expectedContentSize);
+
+ // Flick to the end (row/column 100, and overshoot a bit), and
+ // check that we then end up with the exact content width/height.
+ const qreal secondHalfLength = largeCellCount * cellSizeLarge;
+ const qreal expectedFullSize = (firstHalfLength + secondHalfLength) + accumulatedSpacing;
+ const qreal overshoot = 100;
+ const qreal endPosX = expectedFullSize - tableView->width() + overshoot;
+ const qreal endPosY = expectedFullSize - tableView->height() + overshoot;
+ tableView->setContentX(endPosX);
+ tableView->setContentY(endPosY);
+
+ QCOMPARE(tableView->contentWidth(), expectedFullSize);
+ QCOMPARE(tableView->contentHeight(), expectedFullSize);
+
+ // Flick back to start
+ tableView->setContentX(0);
+ tableView->setContentY(0);
+
+ // Since we move the viewport more than a page, tableview
+ // will jump to the new position and do a rebuild.
+ QVERIFY(tableViewPrivate->polishScheduled);
+ QVERIFY(tableViewPrivate->rebuildScheduled);
+ WAIT_UNTIL_POLISHED;
+
+ // We should now have the same content width/height as when we started
+ QCOMPARE(tableView->contentWidth(), expectedSizeInit);
+ QCOMPARE(tableView->contentHeight(), expectedSizeInit);
+}
+
+void tst_QQuickTableView::checkPageFlicking()
+{
+ // Check that we rebuild the table instead of refilling edges, if the viewport moves
+ // more than a page (the size of TableView).
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int cellWidth = 100;
+ const int cellHeight = 50;
+ auto model = TestModelAsVariant(10000, 10000);
+ const auto &loadedRows = tableViewPrivate->loadedRows;
+ const auto &loadedColumns = tableViewPrivate->loadedColumns;
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Sanity check startup table
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(loadedRows.count(), tableView->height() / cellHeight);
+ QCOMPARE(loadedColumns.count(), tableView->width() / cellWidth);
+
+ // Since all cells have the same size, the average row/column
+ // size found by TableView should be exactly equal to this.
+ QCOMPARE(tableViewPrivate->averageEdgeSize.width(), cellWidth);
+ QCOMPARE(tableViewPrivate->averageEdgeSize.height(), cellHeight);
+
+ QVERIFY(!tableViewPrivate->rebuildScheduled);
+ QCOMPARE(tableViewPrivate->scheduledRebuildOptions, QQuickTableViewPrivate::RebuildOption::None);
+
+ // Flick 5000 columns to the right, and check that this triggers a
+ // rebuild, and that we end up at the expected top-left.
+ const int flickToColumn = 5000;
+ const qreal columnSpacing = tableView->columnSpacing();
+ const qreal flickToColumnInPixels = ((cellWidth + columnSpacing) * flickToColumn) - columnSpacing;
+ tableView->setContentX(flickToColumnInPixels);
+
+ QVERIFY(tableViewPrivate->rebuildScheduled);
+ QVERIFY(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::ViewportOnly);
+ QVERIFY(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn);
+ QVERIFY(!(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow));
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->leftColumn(), flickToColumn);
+ QCOMPARE(loadedColumns.count(), tableView->width() / cellWidth);
+ QCOMPARE(loadedRows.count(), tableView->height() / cellHeight);
+
+ // Flick 5000 rows down as well. Since flicking down should only calculate a new row (but
+ // keep the current column), we deliberatly change the average width to check that it's
+ // actually ignored by the rebuild, and that the column stays the same.
+ tableViewPrivate->averageEdgeSize.rwidth() /= 2;
+
+ const int flickToRow = 5000;
+ const qreal rowSpacing = tableView->rowSpacing();
+ const qreal flickToRowInPixels = ((cellHeight + rowSpacing) * flickToRow) - rowSpacing;
+ tableView->setContentY(flickToRowInPixels);
+
+ QVERIFY(tableViewPrivate->rebuildScheduled);
+ QVERIFY(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::ViewportOnly);
+ QVERIFY(!(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn));
+ QVERIFY(tableViewPrivate->scheduledRebuildOptions & QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->topRow(), flickToColumn);
+ QCOMPARE(tableViewPrivate->leftColumn(), flickToRow);
+ QCOMPARE(loadedRows.count(), tableView->height() / cellHeight);
+ QCOMPARE(loadedColumns.count(), tableView->width() / cellWidth);
+}
+
+void tst_QQuickTableView::checkExplicitContentWidthAndHeight()
+{
+ // Check that you can set a custom contentWidth/Height, and that
+ // TableView doesn't override it while loading more rows and columns.
+ LOAD_TABLEVIEW("contentwidthheight.qml");
+
+ tableView->setContentWidth(1000);
+ tableView->setContentHeight(1000);
+ QCOMPARE(tableView->contentWidth(), 1000);
+ QCOMPARE(tableView->contentHeight(), 1000);
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+
+ // Flick somewhere. It should not affect the contentWidth/Height
+ tableView->setContentX(500);
+ tableView->setContentY(500);
+ QCOMPARE(tableView->contentWidth(), 1000);
+ QCOMPARE(tableView->contentHeight(), 1000);
+}
+
+void tst_QQuickTableView::checkContentXY()
+{
+ // Check that you can bind contentX and contentY to
+ // e.g show the center of the table at start-up
+ LOAD_TABLEVIEW("setcontentpos.qml");
+
+ auto model = TestModelAsVariant(10, 10);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->width(), 400);
+ QCOMPARE(tableView->height(), 400);
+ QCOMPARE(tableView->contentWidth(), 1000);
+ QCOMPARE(tableView->contentHeight(), 1000);
+
+ // Check that the content item is positioned according
+ // to the binding in the QML file (which will set the
+ // viewport to be at the center of the table).
+ const qreal expectedXY = (tableView->contentWidth() - tableView->width()) / 2;
+ QCOMPARE(tableView->contentX(), expectedXY);
+ QCOMPARE(tableView->contentY(), expectedXY);
+
+ // Check that we end up at the correct top-left cell:
+ const qreal delegateWidth = tableViewPrivate->loadedItems.values().first()->item->width();
+ const int expectedCellXY = qCeil(expectedXY / delegateWidth);
+ QCOMPARE(tableViewPrivate->leftColumn(), expectedCellXY);
+ QCOMPARE(tableViewPrivate->topRow(), expectedCellXY);
+}
+
+void tst_QQuickTableView::noDelegate()
+{
+ // Check that you can skip setting a delegate without
+ // it causing any problems (like crashing or asserting).
+ // And then set a delegate, and do a quick check that the
+ // view gets populated as expected.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int rows = 5;
+ const int columns = 5;
+ auto model = TestModelAsVariant(columns, rows);
+ tableView->setModel(model);
+
+ // Start with no delegate, and check
+ // that we end up with no items in the table.
+ tableView->setDelegate(nullptr);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto items = tableViewPrivate->loadedItems;
+ QVERIFY(items.isEmpty());
+
+ // Set a delegate, and check that we end
+ // up with the expected number of items.
+ auto delegate = view->rootObject()->property("delegate").value<QQmlComponent *>();
+ QVERIFY(delegate);
+ tableView->setDelegate(delegate);
+
+ WAIT_UNTIL_POLISHED;
+
+ items = tableViewPrivate->loadedItems;
+ QCOMPARE(items.count(), rows * columns);
+
+ // And then unset the delegate again, and check
+ // that we end up with no items.
+ tableView->setDelegate(nullptr);
+
+ WAIT_UNTIL_POLISHED;
+
+ items = tableViewPrivate->loadedItems;
+ QVERIFY(items.isEmpty());
+}
+
+void tst_QQuickTableView::changeDelegateDuringUpdate()
+{
+ // Check that you can change the delegate (set it to null)
+ // while the TableView is busy loading the table.
+ LOAD_TABLEVIEW("changemodelordelegateduringupdate.qml");
+
+ auto model = TestModelAsVariant(1, 1);
+ tableView->setModel(model);
+ view->rootObject()->setProperty("changeDelegate", true);
+
+ WAIT_UNTIL_POLISHED;
+
+ // We should no longer have a delegate, and no
+ // items should therefore be loaded.
+ QCOMPARE(tableView->delegate(), nullptr);
+ QCOMPARE(tableViewPrivate->loadedItems.size(), 0);
+
+ // Even if the delegate is missing, we still report
+ // the correct size of the model
+ QCOMPARE(tableView->rows(), 1);
+ QCOMPARE(tableView->columns(), 1);
+};
+
+void tst_QQuickTableView::changeModelDuringUpdate()
+{
+ // Check that you can change the model (set it to null)
+ // while the TableView is buzy loading the table.
+ LOAD_TABLEVIEW("changemodelordelegateduringupdate.qml");
+
+ auto model = TestModelAsVariant(1, 1);
+ tableView->setModel(model);
+ view->rootObject()->setProperty("changeModel", true);
+
+ WAIT_UNTIL_POLISHED;
+
+ // We should no longer have a model, and the no
+ // items should therefore be loaded.
+ QVERIFY(tableView->model().isNull());
+ QCOMPARE(tableViewPrivate->loadedItems.size(), 0);
+
+ // The empty model has no rows or columns
+ QCOMPARE(tableView->rows(), 0);
+ QCOMPARE(tableView->columns(), 0);
+};
+
+void tst_QQuickTableView::countDelegateItems_data()
+{
+ QTest::addColumn<QVariant>("model");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("QAIM 1x1") << TestModelAsVariant(1, 1) << 1;
+ QTest::newRow("QAIM 2x1") << TestModelAsVariant(2, 1) << 2;
+ QTest::newRow("QAIM 1x2") << TestModelAsVariant(1, 2) << 2;
+ QTest::newRow("QAIM 2x2") << TestModelAsVariant(2, 2) << 4;
+ QTest::newRow("QAIM 4x4") << TestModelAsVariant(4, 4) << 16;
+
+ QTest::newRow("Number model 1") << QVariant::fromValue(1) << 1;
+ QTest::newRow("Number model 4") << QVariant::fromValue(4) << 4;
+
+ QTest::newRow("QStringList 1") << QVariant::fromValue(QStringList() << "one") << 1;
+ QTest::newRow("QStringList 4") << QVariant::fromValue(QStringList() << "one" << "two" << "three" << "four") << 4;
+}
+
+void tst_QQuickTableView::countDelegateItems()
+{
+ // Assign different models of various sizes, and check that the number of
+ // delegate items in the view matches the size of the model. Note that for
+ // this test to be valid, all items must be within the visible area of the view.
+ QFETCH(QVariant, model);
+ QFETCH(int, count);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+
+ // Check that tableview internals contain the expected number of items
+ auto const items = tableViewPrivate->loadedItems;
+ QCOMPARE(items.count(), count);
+
+ // Check that this also matches the items found in the view
+ auto foundItems = findItems<QQuickItem>(tableView, kDelegateObjectName);
+ QCOMPARE(foundItems.count(), count);
+}
+
+void tst_QQuickTableView::checkLayoutOfEqualSizedDelegateItems_data()
+{
+ QTest::addColumn<QVariant>("model");
+ QTest::addColumn<QSize>("tableSize");
+ QTest::addColumn<QSizeF>("spacing");
+ QTest::addColumn<QMarginsF>("margins");
+
+ // Check spacing together with different table setups
+ QTest::newRow("QAIM 1x1 1,1") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 5x5 0,0") << TestModelAsVariant(5, 5) << QSize(5, 5) << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 5x5 1,0") << TestModelAsVariant(5, 5) << QSize(5, 5) << QSizeF(1, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 5x5 0,1") << TestModelAsVariant(5, 5) << QSize(5, 5) << QSizeF(0, 1) << QMarginsF(0, 0, 0, 0);
+
+ // Check spacing together with margins
+ QTest::newRow("QAIM 1x1 1,1 5555") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(1, 1) << QMarginsF(5, 5, 5, 5);
+ QTest::newRow("QAIM 4x4 0,0 3333") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(0, 0) << QMarginsF(3, 3, 3, 3);
+ QTest::newRow("QAIM 4x4 2,2 1234") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(2, 2) << QMarginsF(1, 2, 3, 4);
+
+ // Check "list" models
+ QTest::newRow("NumberModel 1x4, 0000") << QVariant::fromValue(4) << QSize(1, 4) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QStringList 1x4, 0,0 1111") << QVariant::fromValue(QStringList() << "one" << "two" << "three" << "four")
+ << QSize(1, 4) << QSizeF(0, 0) << QMarginsF(1, 1, 1, 1);
+}
+
+void tst_QQuickTableView::checkLayoutOfEqualSizedDelegateItems()
+{
+ // Check that the geometry of the delegate items are correct
+ QFETCH(QVariant, model);
+ QFETCH(QSize, tableSize);
+ QFETCH(QSizeF, spacing);
+ QFETCH(QMarginsF, margins);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const qreal expectedItemWidth = 100;
+ const qreal expectedItemHeight = 50;
+ const int expectedItemCount = tableSize.width() * tableSize.height();
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+
+ // Setting margins on Flickable should not affect the layout of the
+ // delegate items, since the margins is "transparent" to the TableView.
+ tableView->setLeftMargin(margins.left());
+ tableView->setTopMargin(margins.top());
+ tableView->setRightMargin(margins.right());
+ tableView->setBottomMargin(margins.bottom());
+
+ WAIT_UNTIL_POLISHED;
+
+ auto const items = tableViewPrivate->loadedItems;
+ QVERIFY(!items.isEmpty());
+
+ for (int i = 0; i < expectedItemCount; ++i) {
+ const QQuickItem *item = items[i]->item;
+ QVERIFY(item);
+ QCOMPARE(item->parentItem(), tableView->contentItem());
+
+ const QPoint cell = getContextRowAndColumn(item);
+ qreal expectedX = cell.x() * (expectedItemWidth + spacing.width());
+ qreal expectedY = cell.y() * (expectedItemHeight + spacing.height());
+ QCOMPARE(item->x(), expectedX);
+ QCOMPARE(item->y(), expectedY);
+ QCOMPARE(item->z(), 1);
+ QCOMPARE(item->width(), expectedItemWidth);
+ QCOMPARE(item->height(), expectedItemHeight);
+ }
+}
+
+void tst_QQuickTableView::checkFocusRemoved_data()
+{
+ QTest::addColumn<QString>("focusedItemProp");
+
+ QTest::newRow("delegate root") << QStringLiteral("delegateRoot");
+ QTest::newRow("delegate child") << QStringLiteral("delegateChild");
+}
+
+void tst_QQuickTableView::checkFocusRemoved()
+{
+ // Check that we clear the focus of a delegate item when
+ // a child of the delegate item has focus, and the cell is
+ // flicked out of view.
+ QFETCH(QString, focusedItemProp);
+ LOAD_TABLEVIEW("tableviewfocus.qml");
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto const item = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item;
+ auto const focusedItem = qvariant_cast<QQuickItem *>(item->property(focusedItemProp.toUtf8().data()));
+ QVERIFY(focusedItem);
+ QCOMPARE(tableView->hasActiveFocus(), false);
+ QCOMPARE(focusedItem->hasActiveFocus(), false);
+
+ focusedItem->forceActiveFocus();
+ QCOMPARE(tableView->hasActiveFocus(), true);
+ QCOMPARE(focusedItem->hasActiveFocus(), true);
+
+ // Flick the focused cell out, and check that none of the
+ // items in the table has focus (which means that the reused
+ // item lost focus when it was flicked out). But the tableview
+ // itself will maintain active focus.
+ tableView->setContentX(500);
+ QCOMPARE(tableView->hasActiveFocus(), true);
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ auto const focusedItem2 = qvariant_cast<QQuickItem *>(fxItem->item->property(focusedItemProp.toUtf8().data()));
+ QCOMPARE(focusedItem2->hasActiveFocus(), false);
+ }
+}
+
+void tst_QQuickTableView::fillTableViewButNothingMore_data()
+{
+ QTest::addColumn<QSizeF>("spacing");
+
+ QTest::newRow("0 0,0 0") << QSizeF(0, 0);
+ QTest::newRow("0 10,10 0") << QSizeF(10, 10);
+ QTest::newRow("100 10,10 0") << QSizeF(10, 10);
+ QTest::newRow("0 0,0 100") << QSizeF(0, 0);
+ QTest::newRow("0 10,10 100") << QSizeF(10, 10);
+ QTest::newRow("100 10,10 100") << QSizeF(10, 10);
+}
+
+void tst_QQuickTableView::fillTableViewButNothingMore()
+{
+ // Check that we end up filling the whole visible part of
+ // the tableview with cells, but nothing more.
+ QFETCH(QSizeF, spacing);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int rows = 100;
+ const int columns = 100;
+ auto model = TestModelAsVariant(rows, columns);
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+
+ WAIT_UNTIL_POLISHED;
+
+ auto const topLeftFxItem = tableViewPrivate->loadedTableItem(QPoint(0, 0));
+ auto const topLeftItem = topLeftFxItem->item;
+
+ auto const bottomRightLoadedCell = QPoint(tableViewPrivate->rightColumn(), tableViewPrivate->bottomRow());
+ auto const bottomRightFxItem = tableViewPrivate->loadedTableItem(bottomRightLoadedCell);
+ auto const bottomRightItem = bottomRightFxItem->item;
+ const QPoint bottomRightCell = getContextRowAndColumn(bottomRightItem.data());
+
+ // Check that the right-most item is overlapping the right edge of the view
+ QVERIFY(bottomRightItem->x() < tableView->width());
+ QVERIFY(bottomRightItem->x() + bottomRightItem->width() >= tableView->width() - spacing.width());
+
+ // Check that the actual number of columns matches what we expect
+ qreal cellWidth = bottomRightItem->width() + spacing.width();
+ int expectedColumns = qCeil(tableView->width() / cellWidth);
+ int actualColumns = bottomRightCell.x() + 1;
+ QCOMPARE(actualColumns, expectedColumns);
+
+ // Check that the bottom-most item is overlapping the bottom edge of the view
+ QVERIFY(bottomRightItem->y() < tableView->height());
+ QVERIFY(bottomRightItem->y() + bottomRightItem->height() >= tableView->height() - spacing.height());
+
+ // Check that the actual number of rows matches what we expect
+ qreal cellHeight = bottomRightItem->height() + spacing.height();
+ int expectedRows = qCeil(tableView->height() / cellHeight);
+ int actualRows = bottomRightCell.y() + 1;
+ QCOMPARE(actualRows, expectedRows);
+}
+
+void tst_QQuickTableView::checkInitialAttachedProperties_data()
+{
+ QTest::addColumn<QVariant>("model");
+
+ QTest::newRow("QAIM") << TestModelAsVariant(4, 4);
+ QTest::newRow("Number model") << QVariant::fromValue(4);
+ QTest::newRow("QStringList") << QVariant::fromValue(QStringList() << "0" << "1" << "2" << "3");
+}
+
+void tst_QQuickTableView::checkInitialAttachedProperties()
+{
+ // Check that the context and attached properties inside
+ // the delegate items are what we expect at start-up.
+ QFETCH(QVariant, model);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ const int index = fxItem->index;
+ const auto item = fxItem->item;
+ const auto context = qmlContext(item.data());
+ const QPoint cell = tableViewPrivate->cellAtModelIndex(index);
+ const int contextIndex = context->contextProperty("index").toInt();
+ const QPoint contextCell = getContextRowAndColumn(item.data());
+ const QString contextModelData = context->contextProperty("modelData").toString();
+
+ QCOMPARE(contextCell.y(), cell.y());
+ QCOMPARE(contextCell.x(), cell.x());
+ QCOMPARE(contextIndex, index);
+ QCOMPARE(contextModelData, QStringLiteral("%1").arg(cell.y()));
+ QCOMPARE(getAttachedObject(item)->view(), tableView);
+ }
+}
+
+void tst_QQuickTableView::checkSpacingValues()
+{
+ LOAD_TABLEVIEW("tableviewdefaultspacing.qml");
+
+ int rowCount = 9;
+ int columnCount = 9;
+ int delegateWidth = 15;
+ int delegateHeight = 10;
+ auto model = TestModelAsVariant(rowCount, columnCount);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Default spacing : 0
+ QCOMPARE(tableView->rowSpacing(), 0);
+ QCOMPARE(tableView->columnSpacing(), 0);
+
+ tableView->polish();
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->contentWidth(), columnCount * (delegateWidth + tableView->columnSpacing()) - tableView->columnSpacing());
+ QCOMPARE(tableView->contentHeight(), rowCount * (delegateHeight + tableView->rowSpacing()) - tableView->rowSpacing());
+
+ // Valid spacing assignment
+ tableView->setRowSpacing(42);
+ tableView->setColumnSpacing(12);
+ QCOMPARE(tableView->rowSpacing(), 42);
+ QCOMPARE(tableView->columnSpacing(), 12);
+
+ tableView->polish();
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->contentWidth(), columnCount * (delegateWidth + tableView->columnSpacing()) - tableView->columnSpacing());
+ QCOMPARE(tableView->contentHeight(), rowCount * (delegateHeight + tableView->rowSpacing()) - tableView->rowSpacing());
+
+ // Invalid assignments (should ignore)
+ tableView->setRowSpacing(-1);
+ tableView->setColumnSpacing(-5);
+ tableView->setRowSpacing(INFINITY);
+ tableView->setColumnSpacing(INFINITY);
+ tableView->setRowSpacing(NAN);
+ tableView->setColumnSpacing(NAN);
+ QCOMPARE(tableView->rowSpacing(), 42);
+ QCOMPARE(tableView->columnSpacing(), 12);
+}
+
+void tst_QQuickTableView::checkDelegateParent()
+{
+ // Check that TableView sets the delegate parent before
+ // bindings are evaluated, so that the app can bind to it.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ QVERIFY(view->rootObject()->property("delegateParentSetBeforeCompleted").toBool());
+}
+
+void tst_QQuickTableView::flick_data()
+{
+ QTest::addColumn<QSizeF>("spacing");
+ QTest::addColumn<QMarginsF>("margins");
+ QTest::addColumn<bool>("reuseItems");
+
+ QTest::newRow("s:0 m:0 reuse") << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0) << true;
+ QTest::newRow("s:5 m:0 reuse") << QSizeF(5, 5) << QMarginsF(0, 0, 0, 0) << true;
+ QTest::newRow("s:0 m:20 reuse") << QSizeF(0, 0) << QMarginsF(20, 20, 20, 20) << true;
+ QTest::newRow("s:5 m:20 reuse") << QSizeF(5, 5) << QMarginsF(20, 20, 20, 20) << true;
+ QTest::newRow("s:0 m:0") << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0) << false;
+ QTest::newRow("s:5 m:0") << QSizeF(5, 5) << QMarginsF(0, 0, 0, 0) << false;
+ QTest::newRow("s:0 m:20") << QSizeF(0, 0) << QMarginsF(20, 20, 20, 20) << false;
+ QTest::newRow("s:5 m:20") << QSizeF(5, 5) << QMarginsF(20, 20, 20, 20) << false;
+}
+
+void tst_QQuickTableView::flick()
+{
+ // Check that if we end up with the correct start and end column/row as we flick around
+ // with different table configurations.
+ QFETCH(QSizeF, spacing);
+ QFETCH(QMarginsF, margins);
+ QFETCH(bool, reuseItems);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ const int visualColumnCount = 4;
+ const int visualRowCount = 4;
+ const qreal cellWidth = delegateWidth + spacing.width();
+ const qreal cellHeight = delegateHeight + spacing.height();
+ auto model = TestModelAsVariant(100, 100);
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+ tableView->setLeftMargin(margins.left());
+ tableView->setTopMargin(margins.top());
+ tableView->setRightMargin(margins.right());
+ tableView->setBottomMargin(margins.bottom());
+ tableView->setReuseItems(reuseItems);
+ tableView->setWidth(margins.left() + (visualColumnCount * cellWidth) - spacing.width());
+ tableView->setHeight(margins.top() + (visualRowCount * cellHeight) - spacing.height());
+
+ WAIT_UNTIL_POLISHED;
+
+ // Check the "simple" case if the cells never lands egde-to-edge with the viewport. For
+ // that case we only accept that visible row/columns are loaded.
+ qreal flickValues[] = {0.5, 1.5, 4.5, 20.5, 10.5, 3.5, 1.5, 0.5};
+
+ for (qreal cellsToFlick : flickValues) {
+ // Flick to the beginning of the cell
+ tableView->setContentX(cellsToFlick * cellWidth);
+ tableView->setContentY(cellsToFlick * cellHeight);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ const int expectedTableLeft = int(cellsToFlick - int((margins.left() + spacing.width()) / cellWidth));
+ const int expectedTableTop = int(cellsToFlick - int((margins.top() + spacing.height()) / cellHeight));
+
+ QCOMPARE(tableViewPrivate->leftColumn(), expectedTableLeft);
+ QCOMPARE(tableViewPrivate->rightColumn(), expectedTableLeft + visualColumnCount);
+ QCOMPARE(tableViewPrivate->topRow(), expectedTableTop);
+ QCOMPARE(tableViewPrivate->bottomRow(), expectedTableTop + visualRowCount);
+ }
+}
+
+void tst_QQuickTableView::flickOvershoot_data()
+{
+ QTest::addColumn<QSizeF>("spacing");
+ QTest::addColumn<QMarginsF>("margins");
+ QTest::addColumn<bool>("reuseItems");
+
+ QTest::newRow("s:0 m:0 reuse") << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0) << true;
+ QTest::newRow("s:5 m:0 reuse") << QSizeF(5, 5) << QMarginsF(0, 0, 0, 0) << true;
+ QTest::newRow("s:0 m:20 reuse") << QSizeF(0, 0) << QMarginsF(20, 20, 20, 20) << true;
+ QTest::newRow("s:5 m:20 reuse") << QSizeF(5, 5) << QMarginsF(20, 20, 20, 20) << true;
+ QTest::newRow("s:0 m:0") << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0) << false;
+ QTest::newRow("s:5 m:0") << QSizeF(5, 5) << QMarginsF(0, 0, 0, 0) << false;
+ QTest::newRow("s:0 m:20") << QSizeF(0, 0) << QMarginsF(20, 20, 20, 20) << false;
+ QTest::newRow("s:5 m:20") << QSizeF(5, 5) << QMarginsF(20, 20, 20, 20) << false;
+}
+
+void tst_QQuickTableView::flickOvershoot()
+{
+ // Flick the table completely out and then in again, and see
+ // that we still contains the expected rows/columns
+ // Note that TableView always keeps top-left item loaded, even
+ // when everything is flicked out of view.
+ QFETCH(QSizeF, spacing);
+ QFETCH(QMarginsF, margins);
+ QFETCH(bool, reuseItems);
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int rowCount = 5;
+ const int columnCount = 5;
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ const qreal cellWidth = delegateWidth + spacing.width();
+ const qreal cellHeight = delegateHeight + spacing.height();
+ const qreal tableWidth = margins.left() + margins.right() + (cellWidth * columnCount) - spacing.width();
+ const qreal tableHeight = margins.top() + margins.bottom() + (cellHeight * rowCount) - spacing.height();
+ const int outsideMargin = 10;
+ auto model = TestModelAsVariant(rowCount, columnCount);
+
+ tableView->setModel(model);
+ tableView->setRowSpacing(spacing.height());
+ tableView->setColumnSpacing(spacing.width());
+ tableView->setLeftMargin(margins.left());
+ tableView->setTopMargin(margins.top());
+ tableView->setRightMargin(margins.right());
+ tableView->setBottomMargin(margins.bottom());
+ tableView->setReuseItems(reuseItems);
+ tableView->setWidth(tableWidth - margins.right() - cellWidth / 2);
+ tableView->setHeight(tableHeight - margins.bottom() - cellHeight / 2);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Flick table out of view left
+ tableView->setContentX(-tableView->width() - outsideMargin);
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), 0);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
+
+ // Flick table out of view right
+ tableView->setContentX(tableWidth + outsideMargin);
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->leftColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
+
+ // Flick table out of view on top
+ tableView->setContentX(0);
+ tableView->setContentY(-tableView->height() - outsideMargin);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), 0);
+
+ // Flick table out of view at the bottom
+ tableView->setContentX(0);
+ tableView->setContentY(tableHeight + outsideMargin);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
+
+ // Flick table out of view left and top at the same time
+ tableView->setContentX(-tableView->width() - outsideMargin);
+ tableView->setContentY(-tableView->height() - outsideMargin);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), 0);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), 0);
+
+ // Flick table back to origo
+ tableView->setContentX(0);
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
+
+ // Flick table out of view right and bottom at the same time
+ tableView->setContentX(tableWidth + outsideMargin);
+ tableView->setContentY(tableHeight + outsideMargin);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->leftColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), rowCount - 1);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
+
+ // Flick table back to origo
+ tableView->setContentX(0);
+ tableView->setContentY(0);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableViewPrivate->rightColumn(), columnCount - 1);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableViewPrivate->bottomRow(), rowCount - 1);
+}
+
+void tst_QQuickTableView::checkRowColumnCount()
+{
+ // If we flick several columns (rows) at the same time, check that we don't
+ // end up with loading more delegate items into memory than necessary. We
+ // should free up columns as we go before loading new ones.
+ LOAD_TABLEVIEW("countingtableview.qml");
+
+ const char *maxDelegateCountProp = "maxDelegateCount";
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ auto model = TestModelAsVariant(100, 100);
+ const auto &loadedRows = tableViewPrivate->loadedRows;
+ const auto &loadedColumns = tableViewPrivate->loadedColumns;
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // We expect that the number of created items after start-up should match
+ //the size of the visible table, pluss one extra preloaded row and column.
+ const int qmlCountAfterInit = view->rootObject()->property(maxDelegateCountProp).toInt();
+ const int expectedCount = (loadedColumns.count() + 1) * (loadedRows.count() + 1);
+ QCOMPARE(qmlCountAfterInit, expectedCount);
+
+ // This test will keep track of the maximum number of delegate items TableView
+ // had to show at any point while flicking (in countingtableview.qml). Because
+ // of the geometries chosen for TableView and the delegate, only complete columns
+ // will be shown at start-up.
+ QVERIFY(loadedRows.count() > loadedColumns.count());
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.width(), tableView->width());
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.height(), tableView->height());
+
+ // Flick half an item to the left+up, to force one extra column and row to load before we
+ // start. By doing so, we end up showing the maximum number of rows and columns that will
+ // ever be shown in the view. This will make things less complicated below, when checking
+ // how many items that end up visible while flicking.
+ tableView->setContentX(delegateWidth / 2);
+ tableView->setContentY(delegateHeight / 2);
+ const int qmlCountAfterFirstFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+
+ // Flick a long distance right
+ tableView->setContentX(tableView->width() * 2);
+
+ const int qmlCountAfterLongFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(qmlCountAfterLongFlick, qmlCountAfterFirstFlick);
+
+ // Flick a long distance down
+ tableView->setContentX(tableView->height() * 2);
+
+ const int qmlCountAfterDownFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(qmlCountAfterDownFlick, qmlCountAfterFirstFlick);
+
+ // Flick a long distance left
+ tableView->setContentX(0);
+
+ const int qmlCountAfterLeftFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(qmlCountAfterLeftFlick, qmlCountAfterFirstFlick);
+
+ // Flick a long distance up
+ tableView->setContentY(0);
+
+ const int qmlCountAfterUpFlick = view->rootObject()->property(maxDelegateCountProp).toInt();
+ QCOMPARE(qmlCountAfterUpFlick, qmlCountAfterFirstFlick);
+}
+
+void tst_QQuickTableView::modelSignals()
+{
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ TestModel model(1, 1);
+ tableView->setModel(QVariant::fromValue(&model));
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 1);
+ QCOMPARE(tableView->columns(), 1);
+
+ QVERIFY(model.insertRows(0, 1));
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 2);
+ QCOMPARE(tableView->columns(), 1);
+
+ QVERIFY(model.removeRows(1, 1));
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 1);
+ QCOMPARE(tableView->columns(), 1);
+
+ model.insertColumns(1, 1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 1);
+ QCOMPARE(tableView->columns(), 2);
+
+ model.removeColumns(1, 1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 1);
+ QCOMPARE(tableView->columns(), 1);
+
+ model.setRowCount(10);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 10);
+ QCOMPARE(tableView->columns(), 1);
+
+ model.setColumnCount(10);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 10);
+ QCOMPARE(tableView->columns(), 10);
+
+ model.setRowCount(0);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 0);
+ QCOMPARE(tableView->columns(), 10);
+
+ model.setColumnCount(1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 0);
+ QCOMPARE(tableView->columns(), 1);
+
+ model.setRowCount(10);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 10);
+ QCOMPARE(tableView->columns(), 1);
+
+ model.setColumnCount(10);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 10);
+ QCOMPARE(tableView->columns(), 10);
+
+ model.clear();
+ model.setColumnCount(1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 0);
+ QCOMPARE(tableView->columns(), 1);
+}
+
+void tst_QQuickTableView::checkModelSignalsUpdateLayout()
+{
+ // Check that if the model rearranges rows and emit the
+ // 'layoutChanged' signal, TableView will be updated correctly.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ TestModel model(0, 1);
+ tableView->setModel(QVariant::fromValue(&model));
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->rows(), 0);
+ QCOMPARE(tableView->columns(), 1);
+
+ QString modelRow1Text = QStringLiteral("firstRow");
+ QString modelRow2Text = QStringLiteral("secondRow");
+ model.insertRow(0);
+ model.insertRow(0);
+ model.setModelData(QPoint(0, 0), QSize(1, 1), modelRow1Text);
+ model.setModelData(QPoint(0, 1), QSize(1, 1), modelRow2Text);
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->rows(), 2);
+ QCOMPARE(tableView->columns(), 1);
+
+ QString delegate1text = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item->property("modelDataBinding").toString();
+ QString delegate2text = tableViewPrivate->loadedTableItem(QPoint(0, 1))->item->property("modelDataBinding").toString();
+ QCOMPARE(delegate1text, modelRow1Text);
+ QCOMPARE(delegate2text, modelRow2Text);
+
+ model.swapRows(0, 1);
+ WAIT_UNTIL_POLISHED;
+
+ delegate1text = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item->property("modelDataBinding").toString();
+ delegate2text = tableViewPrivate->loadedTableItem(QPoint(0, 1))->item->property("modelDataBinding").toString();
+ QCOMPARE(delegate1text, modelRow2Text);
+ QCOMPARE(delegate2text, modelRow1Text);
+}
+
+void tst_QQuickTableView::dataChangedSignal()
+{
+ // Check that bindings to the model inside a delegate gets updated
+ // when the model item they bind to changes.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const QString prefix(QStringLiteral("changed"));
+
+ TestModel model(10, 10);
+ tableView->setModel(QVariant::fromValue(&model));
+
+ WAIT_UNTIL_POLISHED;
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ const auto item = tableViewPrivate->loadedTableItem(fxItem->cell)->item;
+ const QString modelDataBindingProperty = item->property(kModelDataBindingProp).toString();
+ QString expectedModelData = QString::number(fxItem->cell.y());
+ QCOMPARE(modelDataBindingProperty, expectedModelData);
+ }
+
+ // Change one cell in the model
+ model.setModelData(QPoint(0, 0), QSize(1, 1), prefix);
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ const QPoint cell = fxItem->cell;
+ const auto modelIndex = model.index(cell.y(), cell.x());
+ QString expectedModelData = model.data(modelIndex, Qt::DisplayRole).toString();
+
+ const auto item = tableViewPrivate->loadedTableItem(fxItem->cell)->item;
+ const QString modelDataBindingProperty = item->property(kModelDataBindingProp).toString();
+
+ QCOMPARE(modelDataBindingProperty, expectedModelData);
+ }
+
+ // Change four cells in one go
+ model.setModelData(QPoint(1, 0), QSize(2, 2), prefix);
+
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ const QPoint cell = fxItem->cell;
+ const auto modelIndex = model.index(cell.y(), cell.x());
+ QString expectedModelData = model.data(modelIndex, Qt::DisplayRole).toString();
+
+ const auto item = tableViewPrivate->loadedTableItem(fxItem->cell)->item;
+ const QString modelDataBindingProperty = item->property(kModelDataBindingProp).toString();
+
+ QCOMPARE(modelDataBindingProperty, expectedModelData);
+ }
+}
+
+void tst_QQuickTableView::checkThatPoolIsDrainedWhenReuseIsFalse()
+{
+ // Check that the reuse pool is drained
+ // immediately when setting reuseItems to false.
+ LOAD_TABLEVIEW("countingtableview.qml");
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // The pool should now contain preloaded items
+ QVERIFY(tableViewPrivate->tableModel->poolSize() > 0);
+ tableView->setReuseItems(false);
+ // The pool should now be empty
+ QCOMPARE(tableViewPrivate->tableModel->poolSize(), 0);
+}
+
+void tst_QQuickTableView::checkIfDelegatesAreReused_data()
+{
+ QTest::addColumn<bool>("reuseItems");
+
+ QTest::newRow("reuse = true") << true;
+ QTest::newRow("reuse = false") << false;
+}
+
+void tst_QQuickTableView::checkIfDelegatesAreReused()
+{
+ // Check that we end up reusing delegate items while flicking if
+ // TableView has reuseItems set to true, but otherwise not.
+ QFETCH(bool, reuseItems);
+ LOAD_TABLEVIEW("countingtableview.qml");
+
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ const int pageFlickCount = 4;
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+ tableView->setReuseItems(reuseItems);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Flick half an item to the side, to force one extra row and column to load before we start.
+ // This will make things less complicated below, when checking how many times the items
+ // have been reused (all items will then report the same number).
+ tableView->setContentX(delegateWidth / 2);
+ tableView->setContentY(delegateHeight / 2);
+ QCOMPARE(tableViewPrivate->tableModel->poolSize(), 0);
+
+ // Some items have already been pooled and reused after we moved the content view, because
+ // we preload one extra row and column at start-up. So reset the count-properties back to 0
+ // before we continue.
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ fxItem->item->setProperty("pooledCount", 0);
+ fxItem->item->setProperty("reusedCount", 0);
+ }
+
+ const int visibleColumnCount = tableViewPrivate->loadedColumns.count();
+ const int visibleRowCount = tableViewPrivate->loadedRows.count();
+ const int delegateCountAfterInit = view->rootObject()->property(kDelegatesCreatedCountProp).toInt();
+
+ for (int column = 1; column <= (visibleColumnCount * pageFlickCount); ++column) {
+ // Flick columns to the left (and add one pixel to ensure the left column is completely out)
+ tableView->setContentX((delegateWidth * column) + 1);
+ // Check that the number of delegate items created so far is what we expect.
+ const int delegatesCreatedCount = view->rootObject()->property(kDelegatesCreatedCountProp).toInt();
+ int expectedCount = delegateCountAfterInit + (reuseItems ? 0 : visibleRowCount * column);
+ QCOMPARE(delegatesCreatedCount, expectedCount);
+ }
+
+ // Check that each delegate item has been reused as many times
+ // as we have flicked pages (if reuse is enabled).
+ for (auto fxItem : tableViewPrivate->loadedItems) {
+ int pooledCount = fxItem->item->property("pooledCount").toInt();
+ int reusedCount = fxItem->item->property("reusedCount").toInt();
+ if (reuseItems) {
+ QCOMPARE(pooledCount, pageFlickCount);
+ QCOMPARE(reusedCount, pageFlickCount);
+ } else {
+ QCOMPARE(pooledCount, 0);
+ QCOMPARE(reusedCount, 0);
+ }
+ }
+}
+
+void tst_QQuickTableView::checkIfDelegatesAreReusedAsymmetricTableSize()
+{
+ // Check that we end up reusing all delegate items while flicking, also if the table contain
+ // more columns than rows. In that case, if we flick out a whole row, we'll move a lot of
+ // items into the pool. And if we then start flicking in columns, we'll only reuse a few of
+ // them for each column. Still, we don't want the pool to release the superfluous items after
+ // each load, since they are still in circulation and will be needed once we flick in a new
+ // row at the end of the test.
+ LOAD_TABLEVIEW("countingtableview.qml");
+
+ const int columnCount = 20;
+ const int rowCount = 2;
+ const qreal delegateWidth = tableView->width() / columnCount;
+ const qreal delegateHeight = (tableView->height() / rowCount) + 10;
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ // Let the height of each row be much bigger than the width of each column.
+ view->rootObject()->setProperty("delegateWidth", delegateWidth);
+ view->rootObject()->setProperty("delegateHeight", delegateHeight);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto initialTopLeftItem = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item;
+ QVERIFY(initialTopLeftItem);
+ int pooledCount = initialTopLeftItem->property("pooledCount").toInt();
+ int reusedCount = initialTopLeftItem->property("reusedCount").toInt();
+ QCOMPARE(pooledCount, 0);
+ QCOMPARE(reusedCount, 0);
+
+ // Flick half an item left+down, to force one extra row and column to load. By doing
+ // so, we force the maximum number of rows and columns to show before we start the test.
+ // This will make things less complicated below, when checking how many
+ // times the items have been reused (all items will then report the same number).
+ tableView->setContentX(delegateWidth * 0.5);
+ tableView->setContentY(delegateHeight * 0.5);
+
+ // Since we have flicked half a delegate to the left, the number of visible
+ // columns is now one more than the column count were when we started the test.
+ const int visibleColumnCount = tableViewPrivate->loadedColumns.count();
+ QCOMPARE(visibleColumnCount, columnCount + 1);
+
+ // We expect no items to have been pooled so far
+ pooledCount = initialTopLeftItem->property("pooledCount").toInt();
+ reusedCount = initialTopLeftItem->property("reusedCount").toInt();
+ QCOMPARE(pooledCount, 0);
+ QCOMPARE(reusedCount, 0);
+ QCOMPARE(tableViewPrivate->tableModel->poolSize(), 0);
+
+ // Flick one row out of view. This will move one whole row of items into the
+ // pool without reusing them, since no new row is exposed at the bottom.
+ tableView->setContentY(delegateHeight + 1);
+ pooledCount = initialTopLeftItem->property("pooledCount").toInt();
+ reusedCount = initialTopLeftItem->property("reusedCount").toInt();
+ QCOMPARE(pooledCount, 1);
+ QCOMPARE(reusedCount, 0);
+ QCOMPARE(tableViewPrivate->tableModel->poolSize(), visibleColumnCount);
+
+ const int delegateCountAfterInit = view->rootObject()->property(kDelegatesCreatedCountProp).toInt();
+
+ // Start flicking in a lot of columns, and check that the created count stays the same
+ for (int column = 1; column <= 10; ++column) {
+ tableView->setContentX((delegateWidth * column) + 10);
+ const int delegatesCreatedCount = view->rootObject()->property(kDelegatesCreatedCountProp).toInt();
+ // Since we reuse items while flicking, the created count should stay the same
+ QCOMPARE(delegatesCreatedCount, delegateCountAfterInit);
+ // Since we flick out just as many columns as we flick in, the pool size should stay the same
+ QCOMPARE(tableViewPrivate->tableModel->poolSize(), visibleColumnCount);
+ }
+
+ // Finally, flick one row back into view (but without flicking so far that we push the third
+ // row out and into the pool). The pool should still contain the exact amount of items that
+ // we had after we flicked the first row out. And this should be exactly the amount of items
+ // needed to load the row back again. And this also means that the pool count should then return
+ // back to 0.
+ tableView->setContentY(delegateHeight - 1);
+ const int delegatesCreatedCount = view->rootObject()->property(kDelegatesCreatedCountProp).toInt();
+ QCOMPARE(delegatesCreatedCount, delegateCountAfterInit);
+ QCOMPARE(tableViewPrivate->tableModel->poolSize(), 0);
+}
+
+void tst_QQuickTableView::checkContextProperties_data()
+{
+ QTest::addColumn<QVariant>("model");
+ QTest::addColumn<bool>("reuseItems");
+
+ auto stringList = QStringList();
+ for (int i = 0; i < 100; ++i)
+ stringList.append(QString::number(i));
+
+ QTest::newRow("QAIM, reuse=false") << TestModelAsVariant(100, 100) << false;
+ QTest::newRow("QAIM, reuse=true") << TestModelAsVariant(100, 100) << true;
+ QTest::newRow("Number model, reuse=false") << QVariant::fromValue(100) << false;
+ QTest::newRow("Number model, reuse=true") << QVariant::fromValue(100) << true;
+ QTest::newRow("QStringList, reuse=false") << QVariant::fromValue(stringList) << false;
+ QTest::newRow("QStringList, reuse=true") << QVariant::fromValue(stringList) << true;
+}
+
+void tst_QQuickTableView::checkContextProperties()
+{
+ // Check that the context properties of the delegate items
+ // are what we expect while flicking, with or without item recycling.
+ QFETCH(QVariant, model);
+ QFETCH(bool, reuseItems);
+ LOAD_TABLEVIEW("countingtableview.qml");
+
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ const int rowCount = 100;
+ const int pageFlickCount = 3;
+
+ tableView->setModel(model);
+ tableView->setReuseItems(reuseItems);
+
+ WAIT_UNTIL_POLISHED;
+
+ const int visibleRowCount = qMin(tableView->rows(), qCeil(tableView->height() / delegateHeight));
+ const int visibleColumnCount = qMin(tableView->columns(), qCeil(tableView->width() / delegateWidth));
+
+ for (int row = 1; row <= (visibleRowCount * pageFlickCount); ++row) {
+ // Flick rows up
+ tableView->setContentY((delegateHeight * row) + (delegateHeight / 2));
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ for (int col = 0; col < visibleColumnCount; ++col) {
+ const auto item = tableViewPrivate->loadedTableItem(QPoint(col, row))->item;
+ const auto context = qmlContext(item.data());
+ const int contextIndex = context->contextProperty("index").toInt();
+ const int contextRow = context->contextProperty("row").toInt();
+ const int contextColumn = context->contextProperty("column").toInt();
+ const QString contextModelData = context->contextProperty("modelData").toString();
+
+ QCOMPARE(contextIndex, row + (col * rowCount));
+ QCOMPARE(contextRow, row);
+ QCOMPARE(contextColumn, col);
+ QCOMPARE(contextModelData, QStringLiteral("%1").arg(row));
+ }
+ }
+}
+
+void tst_QQuickTableView::checkContextPropertiesQQmlListProperyModel_data()
+{
+ QTest::addColumn<bool>("reuseItems");
+
+ QTest::newRow("reuse=false") << false;
+ QTest::newRow("reuse=true") << true;
+}
+
+void tst_QQuickTableView::checkContextPropertiesQQmlListProperyModel()
+{
+ // Check that the context properties of the delegate items
+ // are what we expect while flicking, with or without item recycling.
+ // This test hard-codes the model to be a QQmlListPropertyModel from
+ // within the qml file.
+ QFETCH(bool, reuseItems);
+ LOAD_TABLEVIEW("qqmllistpropertymodel.qml");
+
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ const int rowCount = 100;
+ const int pageFlickCount = 3;
+
+ tableView->setReuseItems(reuseItems);
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ const int visibleRowCount = qMin(tableView->rows(), qCeil(tableView->height() / delegateHeight));
+ const int visibleColumnCount = qMin(tableView->columns(), qCeil(tableView->width() / delegateWidth));
+
+ for (int row = 1; row <= (visibleRowCount * pageFlickCount); ++row) {
+ // Flick rows up
+ tableView->setContentY((delegateHeight * row) + (delegateHeight / 2));
+ tableView->polish();
+
+ WAIT_UNTIL_POLISHED;
+
+ for (int col = 0; col < visibleColumnCount; ++col) {
+ const auto item = tableViewPrivate->loadedTableItem(QPoint(col, row))->item;
+ const auto context = qmlContext(item.data());
+ const int contextIndex = context->contextProperty("index").toInt();
+ const int contextRow = context->contextProperty("row").toInt();
+ const int contextColumn = context->contextProperty("column").toInt();
+ const QObject *contextModelData = qvariant_cast<QObject *>(context->contextProperty("modelData"));
+ const QString modelDataProperty = contextModelData->property("someCustomProperty").toString();
+
+ QCOMPARE(contextIndex, row + (col * rowCount));
+ QCOMPARE(contextRow, row);
+ QCOMPARE(contextColumn, col);
+ QCOMPARE(modelDataProperty, QStringLiteral("%1").arg(row));
+ }
+ }
+}
+
+void tst_QQuickTableView::checkRowAndColumnChangedButNotIndex()
+{
+ // Check that context row and column changes even if the index stays the
+ // same when the item is reused. This can happen in rare cases if the item
+ // is first used at e.g (row 1, col 0), but then reused at (row 0, col 1)
+ // while the model has changed row count in-between.
+ LOAD_TABLEVIEW("checkrowandcolumnnotchanged.qml");
+
+ TestModel model(2, 1);
+ tableView->setModel(QVariant::fromValue(&model));
+
+ WAIT_UNTIL_POLISHED;
+
+ model.removeRow(1);
+ model.insertColumn(1);
+ tableView->forceLayout();
+
+ const auto item = tableViewPrivate->loadedTableItem(QPoint(1, 0))->item;
+ const auto context = qmlContext(item.data());
+ const int contextIndex = context->contextProperty("index").toInt();
+ const int contextRow = context->contextProperty("row").toInt();
+ const int contextColumn = context->contextProperty("column").toInt();
+
+ QCOMPARE(contextIndex, 1);
+ QCOMPARE(contextRow, 0);
+ QCOMPARE(contextColumn, 1);
+}
+
+void tst_QQuickTableView::checkChangingModelFromDelegate()
+{
+ // Check that we don't restart a rebuild of the table
+ // while we're in the middle of rebuilding it from before
+ LOAD_TABLEVIEW("changemodelfromdelegate.qml");
+
+ // Set addRowFromDelegate. This will trigger the QML code to add a new
+ // row and call forceLayout(). When TableView instantiates the first
+ // delegate in the new row, the Component.onCompleted handler will try to
+ // add a new row. But since we're currently rebuilding, this should be
+ // scheduled for later.
+ view->rootObject()->setProperty("addRowFromDelegate", true);
+
+ // We now expect two rows in the table, one more than initially
+ QCOMPARE(tableViewPrivate->tableSize.height(), 2);
+ QCOMPARE(tableViewPrivate->loadedRows.count(), 2);
+
+ // And since the QML code tried to add another row as well, we
+ // expect rebuildScheduled to be true, and a polish event to be pending.
+ QCOMPARE(tableViewPrivate->rebuildScheduled, true);
+ QCOMPARE(tableViewPrivate->polishScheduled, true);
+ WAIT_UNTIL_POLISHED;
+
+ // After handling the polish event, we expect also the third row to now be added
+ QCOMPARE(tableViewPrivate->tableSize.height(), 3);
+ QCOMPARE(tableViewPrivate->loadedRows.count(), 3);
+}
+
+void tst_QQuickTableView::checkRebuildViewportOnly()
+{
+ // Check that we only rebuild from the current top-left cell
+ // when you add or remove rows and columns. There should be
+ // no need to do a rebuild from scratch in such cases.
+ LOAD_TABLEVIEW("countingtableview.qml");
+
+ const char *propName = "delegatesCreatedCount";
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+
+ TestModel model(100, 100);
+ tableView->setModel(QVariant::fromValue(&model));
+
+ WAIT_UNTIL_POLISHED;
+
+ // Flick to row/column 50, 50
+ tableView->setContentX(delegateWidth * 50);
+ tableView->setContentY(delegateHeight * 50);
+
+ // Set reuse items to false, just to make it easier to
+ // check the number of items created during a rebuild.
+ tableView->setReuseItems(false);
+ const int itemCountBeforeRebuild = tableViewPrivate->loadedItems.count();
+
+ // Since all cells have the same size, we expect that we end up creating
+ // the same amount of items that were already showing before, even after
+ // adding or removing rows and columns.
+ view->rootObject()->setProperty(propName, 0);
+ model.insertRow(51);
+ WAIT_UNTIL_POLISHED;
+ int countAfterRebuild = view->rootObject()->property(propName).toInt();
+ QCOMPARE(countAfterRebuild, itemCountBeforeRebuild);
+
+ view->rootObject()->setProperty(propName, 0);
+ model.removeRow(51);
+ WAIT_UNTIL_POLISHED;
+ countAfterRebuild = view->rootObject()->property(propName).toInt();
+ QCOMPARE(countAfterRebuild, itemCountBeforeRebuild);
+
+ view->rootObject()->setProperty(propName, 0);
+ model.insertColumn(51);
+ WAIT_UNTIL_POLISHED;
+ countAfterRebuild = view->rootObject()->property(propName).toInt();
+ QCOMPARE(countAfterRebuild, itemCountBeforeRebuild);
+
+ view->rootObject()->setProperty(propName, 0);
+ model.removeColumn(51);
+ WAIT_UNTIL_POLISHED;
+ countAfterRebuild = view->rootObject()->property(propName).toInt();
+ QCOMPARE(countAfterRebuild, itemCountBeforeRebuild);
+}
+
+void tst_QQuickTableView::useDelegateChooserWithoutDefault()
+{
+ // Check that the application issues a warning (but doesn't e.g
+ // crash) if the delegate chooser doesn't cover all cells
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*failed"));
+ LOAD_TABLEVIEW("usechooserwithoutdefault.qml");
+ auto model = TestModelAsVariant(2, 1);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+};
+
+void tst_QQuickTableView::checkTableviewInsideAsyncLoader()
+{
+ // Check that you can put a TableView inside an async Loader, and
+ // that the delegate items are created before the loader is ready.
+ LOAD_TABLEVIEW_ASYNC("asyncplain.qml");
+
+ // At this point the Loader has finished
+ QCOMPARE(loader->status(), QQuickLoader::Ready);
+
+ // Check that TableView has finished building
+ QCOMPARE(tableViewPrivate->rebuildScheduled, false);
+ QCOMPARE(tableViewPrivate->rebuildState, QQuickTableViewPrivate::RebuildState::Done);
+
+ // Check that all expected delegate items have been loaded
+ const qreal delegateWidth = 100;
+ const qreal delegateHeight = 50;
+ int expectedColumns = qCeil(tableView->width() / delegateWidth);
+ int expectedRows = qCeil(tableView->height() / delegateHeight);
+ QCOMPARE(tableViewPrivate->loadedColumns.count(), expectedColumns);
+ QCOMPARE(tableViewPrivate->loadedRows.count(), expectedRows);
+
+ // Check that the loader was still in a loading state while TableView was creating
+ // delegate items. If we delayed creating delegate items until we got the first
+ // updatePolish() callback in QQuickTableView, this would not be the case.
+ auto statusWhenDelegate0_0Completed = qvariant_cast<QQuickLoader::Status>(
+ loader->item()->property("statusWhenDelegate0_0Created"));
+ auto statusWhenDelegate5_5Completed = qvariant_cast<QQuickLoader::Status>(
+ loader->item()->property("statusWhenDelegate5_5Created"));
+ QCOMPARE(statusWhenDelegate0_0Completed, QQuickLoader::Loading);
+ QCOMPARE(statusWhenDelegate5_5Completed, QQuickLoader::Loading);
+
+ // Check that TableView had a valid geometry when we started to build. If the build
+ // was started too early (e.g upon QQuickTableView::componentComplete), width and
+ // height would still be 0 since the bindings would not have been evaluated yet.
+ qreal width = loader->item()->property("tableViewWidthWhileBuilding").toReal();
+ qreal height = loader->item()->property("tableViewHeightWhileBuilding").toReal();
+ QVERIFY(width > 0);
+ QVERIFY(height > 0);
+};
+
+#define INT_LIST(indices) QVariant::fromValue(QList<int>() << indices)
+
+void tst_QQuickTableView::hideRowsAndColumns_data()
+{
+ QTest::addColumn<QVariant>("rowsToHide");
+ QTest::addColumn<QVariant>("columnsToHide");
+
+ const auto emptyList = QVariant::fromValue(QList<int>());
+
+ // Hide rows
+ QTest::newRow("first") << INT_LIST(0) << emptyList;
+ QTest::newRow("middle 1") << INT_LIST(1) << emptyList;
+ QTest::newRow("middle 3") << INT_LIST(3) << emptyList;
+ QTest::newRow("last") << INT_LIST(4) << emptyList;
+
+ QTest::newRow("subsequent 0,1") << INT_LIST(0 << 1) << emptyList;
+ QTest::newRow("subsequent 1,2") << INT_LIST(1 << 2) << emptyList;
+ QTest::newRow("subsequent 3,4") << INT_LIST(3 << 4) << emptyList;
+
+ QTest::newRow("all but first") << INT_LIST(1 << 2 << 3 << 4) << emptyList;
+ QTest::newRow("all but last") << INT_LIST(0 << 1 << 2 << 3) << emptyList;
+ QTest::newRow("all but middle") << INT_LIST(0 << 1 << 3 << 4) << emptyList;
+
+ // Hide columns
+ QTest::newRow("first") << emptyList << INT_LIST(0);
+ QTest::newRow("middle 1") << emptyList << INT_LIST(1);
+ QTest::newRow("middle 3") << emptyList << INT_LIST(3);
+ QTest::newRow("last") << emptyList << INT_LIST(4);
+
+ QTest::newRow("subsequent 0,1") << emptyList << INT_LIST(0 << 1);
+ QTest::newRow("subsequent 1,2") << emptyList << INT_LIST(1 << 2);
+ QTest::newRow("subsequent 3,4") << emptyList << INT_LIST(3 << 4);
+
+ QTest::newRow("all but first") << emptyList << INT_LIST(1 << 2 << 3 << 4);
+ QTest::newRow("all but last") << emptyList << INT_LIST(0 << 1 << 2 << 3);
+ QTest::newRow("all but middle") << emptyList << INT_LIST(0 << 1 << 3 << 4);
+
+ // Hide both rows and columns at the same time
+ QTest::newRow("first") << INT_LIST(0) << INT_LIST(0);
+ QTest::newRow("middle 1") << INT_LIST(1) << INT_LIST(1);
+ QTest::newRow("middle 3") << INT_LIST(3) << INT_LIST(3);
+ QTest::newRow("last") << INT_LIST(4) << INT_LIST(4);
+
+ QTest::newRow("subsequent 0,1") << INT_LIST(0 << 1) << INT_LIST(0 << 1);
+ QTest::newRow("subsequent 1,2") << INT_LIST(1 << 2) << INT_LIST(1 << 2);
+ QTest::newRow("subsequent 3,4") << INT_LIST(3 << 4) << INT_LIST(3 << 4);
+
+ QTest::newRow("all but first") << INT_LIST(1 << 2 << 3 << 4) << INT_LIST(1 << 2 << 3 << 4);
+ QTest::newRow("all but last") << INT_LIST(0 << 1 << 2 << 3) << INT_LIST(0 << 1 << 2 << 3);
+ QTest::newRow("all but middle") << INT_LIST(0 << 1 << 3 << 4) << INT_LIST(0 << 1 << 3 << 4);
+
+ // Hide all rows and columns
+ QTest::newRow("all") << INT_LIST(0 << 1 << 2 << 3 << 4) << INT_LIST(0 << 1 << 2 << 3 << 4);
+}
+
+void tst_QQuickTableView::hideRowsAndColumns()
+{
+ // Check that you can hide the first row (corner case)
+ // and that we load the other columns as expected.
+ QFETCH(QVariant, rowsToHide);
+ QFETCH(QVariant, columnsToHide);
+ LOAD_TABLEVIEW("hiderowsandcolumns.qml");
+
+ const QList<int> rowsToHideList = qvariant_cast<QList<int>>(rowsToHide);
+ const QList<int> columnsToHideList = qvariant_cast<QList<int>>(columnsToHide);
+ const int modelSize = 5;
+ auto model = TestModelAsVariant(modelSize, modelSize);
+ view->rootObject()->setProperty("rowsToHide", rowsToHide);
+ view->rootObject()->setProperty("columnsToHide", columnsToHide);
+
+ tableView->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ const int expectedRowCount = modelSize - rowsToHideList.count();
+ const int expectedColumnCount = modelSize - columnsToHideList.count();
+ QCOMPARE(tableViewPrivate->loadedRows.count(), expectedRowCount);
+ QCOMPARE(tableViewPrivate->loadedColumns.count(), expectedColumnCount);
+
+ for (const int row : tableViewPrivate->loadedRows.keys())
+ QVERIFY(!rowsToHideList.contains(row));
+
+ for (const int column : tableViewPrivate->loadedColumns.keys())
+ QVERIFY(!columnsToHideList.contains(column));
+}
+
+void tst_QQuickTableView::checkThatRevisionedPropertiesCannotBeUsedInOldImports()
+{
+ // Check that if you use a QQmlAdaptorModel together with a Repeater, the
+ // revisioned context properties 'row' and 'column' are not accessible.
+ LOAD_TABLEVIEW("checkmodelpropertyrevision.qml");
+ const int resolvedRow = view->rootObject()->property("resolvedDelegateRow").toInt();
+ const int resolvedColumn = view->rootObject()->property("resolvedDelegateColumn").toInt();
+ QCOMPARE(resolvedRow, 42);
+ QCOMPARE(resolvedColumn, 42);
+}
+
+QTEST_MAIN(tst_QQuickTableView)
+
+#include "tst_qquicktableview.moc"
diff --git a/tests/auto/quick/qquicktext/data/contentHeight.qml b/tests/auto/quick/qquicktext/data/contentHeight.qml
new file mode 100644
index 0000000000..472e97078e
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/contentHeight.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.9
+
+Text{
+ width: 200
+ height: contentHeight
+ text: ''
+}
diff --git a/tests/auto/quick/qquicktext/data/elideParentChanged.qml b/tests/auto/quick/qquicktext/data/elideParentChanged.qml
new file mode 100644
index 0000000000..f605cf58f1
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/elideParentChanged.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+Item {
+ width: 100
+ height: 30
+
+ Text {
+ width: parent ? parent.width : 0
+ height: parent ? parent.height : 0
+ elide: Text.ElideRight
+ text: "wot"
+ }
+}
diff --git a/tests/auto/quick/qquicktext/data/implicitSizeChangeRewrap.qml b/tests/auto/quick/qquicktext/data/implicitSizeChangeRewrap.qml
new file mode 100644
index 0000000000..fb8626a75a
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/implicitSizeChangeRewrap.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+import QtQuick.Layouts 1.0
+
+Item
+{
+ id : _rootItem
+ width : 200
+ height : 1000
+ ColumnLayout
+ {
+ id : _textContainer
+ anchors.centerIn: parent
+ Layout.maximumWidth: (_rootItem.width - 40) // to have some space left / right
+ Text
+ {
+ id : text
+ objectName: "text"
+ font.italic: true
+ textFormat: Text.RichText
+ horizontalAlignment : Text.AlignHCenter
+ verticalAlignment : Text.AlignVCenter
+ wrapMode: Text.Wrap
+ Layout.maximumWidth: (_rootItem.width - 60)
+ Component.onCompleted: text.text = "This is a too long text for the interface with a stupid path also too long -> /home/long/long/long/to/force/it/to/need/to/wrap This is a too long text for the interface with a stupid path also too long -> /home/long/long/long/to/force/it/to/need/to/wrap This is a too long text for the interface with a stupid path also too long -> /home/long/long/long/to/force/it/to/need/to/wrap This is a too long text for the interface with a stupid path also too long -> /home/long/long/long/to/force/it/to/need/to/wrap"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktext/qquicktext.pro b/tests/auto/quick/qquicktext/qquicktext.pro
index 4f4b77ed7b..fdea9dcddd 100644
--- a/tests/auto/quick/qquicktext/qquicktext.pro
+++ b/tests/auto/quick/qquicktext/qquicktext.pro
@@ -4,7 +4,6 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qquicktext.cpp
-INCLUDEPATH += ../../shared/
HEADERS += ../../shared/testhttpserver.h
SOURCES += ../../shared/testhttpserver.cpp
@@ -12,4 +11,4 @@ include (../../shared/util.pri)
TESTDATA = data/*
-QT += core-private gui-private qml-private quick-private network testlib
+QT += core-private gui-private qml-private quick-private network testlib qmltest
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index f741062d42..fd0ba0f49b 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -32,12 +32,14 @@
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
+#include <QtQuickTest/QtQuickTest>
#include <private/qquicktext_p_p.h>
#include <private/qquicktextdocument_p.h>
#include <private/qquickvaluetypes_p.h>
#include <QFontMetrics>
#include <qmath.h>
#include <QtQuick/QQuickView>
+#include <QtQuick/qquickitemgrabresult.h>
#include <private/qguiapplication_p.h>
#include <limits.h>
#include <QtGui/QMouseEvent>
@@ -64,6 +66,7 @@ private slots:
void width();
void wrap();
void elide();
+ void elideParentChanged();
void multilineElide_data();
void multilineElide();
void implicitElide_data();
@@ -103,6 +106,7 @@ private slots:
void implicitSize_data();
void implicitSize();
+ void implicitSizeChangeRewrap();
void dependentImplicitSizes();
void contentSize();
void implicitSizeBinding_data();
@@ -156,6 +160,8 @@ private slots:
void fontInfo();
+ void initialContentHeight();
+
private:
QStringList standard;
QStringList richText;
@@ -238,7 +244,7 @@ tst_qquicktext::tst_qquicktext()
QQuickView *tst_qquicktext::createView(const QString &filename)
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setSource(QUrl::fromLocalFile(filename));
return window;
@@ -251,7 +257,7 @@ void tst_qquicktext::text()
textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->text(), QString(""));
QCOMPARE(textObject->width(), qreal(0));
@@ -266,7 +272,7 @@ void tst_qquicktext::text()
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->text(), standard.at(i));
QVERIFY(textObject->width() > 0);
@@ -280,7 +286,7 @@ void tst_qquicktext::text()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QString expected = richText.at(i);
QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
QVERIFY(textObject->width() > 0);
@@ -297,7 +303,7 @@ void tst_qquicktext::width()
textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 0.);
delete textObject;
@@ -336,7 +342,7 @@ void tst_qquicktext::width()
metricWidth = layout.boundingRect().width();
} else {
QFontMetricsF fm(f);
- metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
+ metricWidth = fm.size(Qt::TextExpandTabs | Qt::TextShowMnemonic, standard.at(i)).width();
}
QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
@@ -344,7 +350,7 @@ void tst_qquicktext::width()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QVERIFY(textObject->boundingRect().width() > 0);
QCOMPARE(textObject->width(), qreal(metricWidth));
QVERIFY(textObject->textFormat() == QQuickText::AutoText); // setting text doesn't change format
@@ -360,14 +366,14 @@ void tst_qquicktext::width()
QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QVERIFY(textPrivate->extra.isAllocated());
QTextDocument *doc = textPrivate->extra->doc;
- QVERIFY(doc != 0);
+ QVERIFY(doc != nullptr);
QCOMPARE(int(textObject->width()), int(doc->idealWidth()));
QCOMPARE(textObject->textFormat(), QQuickText::RichText);
@@ -386,7 +392,7 @@ void tst_qquicktext::wrap()
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
textHeight = textObject->height();
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->wrapMode(), QQuickText::WordWrap);
QCOMPARE(textObject->width(), 300.);
@@ -400,7 +406,7 @@ void tst_qquicktext::wrap()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
QVERIFY(textObject->height() > textHeight);
@@ -418,7 +424,7 @@ void tst_qquicktext::wrap()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
QVERIFY(textObject->height() > textHeight);
@@ -437,16 +443,16 @@ void tst_qquicktext::wrap()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
QVERIFY(textObject->height() > textHeight);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QVERIFY(textPrivate->extra.isAllocated());
QTextDocument *doc = textPrivate->extra->doc;
- QVERIFY(doc != 0);
+ QVERIFY(doc != nullptr);
textObject->setWidth(doc->idealWidth());
QCOMPARE(textObject->width(), doc->idealWidth());
QVERIFY(textObject->height() > textHeight);
@@ -466,7 +472,7 @@ void tst_qquicktext::wrap()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
QVERIFY(textObject->implicitHeight() > textHeight);
@@ -554,6 +560,45 @@ void tst_qquicktext::elide()
}
}
+// QTBUG-60328
+// Tests that text with elide set is rendered after
+// having its parent cleared and then set again.
+void tst_qquicktext::elideParentChanged()
+{
+ QQuickView window;
+ window.setSource(testFileUrl("elideParentChanged.qml"));
+ QTRY_COMPARE(window.status(), QQuickView::Ready);
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QQuickItem *root = window.rootObject();
+ QVERIFY(root);
+ QCOMPARE(root->childItems().size(), 1);
+
+ // Store a snapshot of the scene so that we can compare it later.
+ QSharedPointer<QQuickItemGrabResult> grabResult = root->grabToImage();
+ QTRY_VERIFY(!grabResult->image().isNull());
+ const QImage expectedItemImageGrab(grabResult->image());
+
+ // Clear the text's parent. It shouldn't render anything.
+ QQuickItem *text = root->childItems().first();
+ text->setParentItem(nullptr);
+ QCOMPARE(text->width(), 0.0);
+ QCOMPARE(text->height(), 0.0);
+
+ // Set the parent back to what it was. The text should
+ // be rendered identically to how it was before.
+ text->setParentItem(root);
+ QCOMPARE(text->width(), 100.0);
+ QCOMPARE(text->height(), 30.0);
+
+ grabResult = root->grabToImage();
+ QTRY_VERIFY(!grabResult->image().isNull());
+ const QImage actualItemImageGrab(grabResult->image());
+ QCOMPARE(actualItemImageGrab, expectedItemImageGrab);
+}
+
void tst_qquicktext::multilineElide_data()
{
QTest::addColumn<QQuickText::TextFormat>("format");
@@ -567,7 +612,7 @@ void tst_qquicktext::multilineElide()
QScopedPointer<QQuickView> window(createView(testFile("multilineelide.qml")));
QQuickText *myText = qobject_cast<QQuickText*>(window->rootObject());
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
myText->setTextFormat(format);
QCOMPARE(myText->lineCount(), 3);
@@ -667,11 +712,11 @@ void tst_qquicktext::textFormat()
textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->textFormat(), QQuickText::RichText);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QVERIFY(textPrivate->richText);
delete textObject;
@@ -681,11 +726,11 @@ void tst_qquicktext::textFormat()
textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\" }", QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->textFormat(), QQuickText::AutoText);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QVERIFY(textPrivate->styledText);
delete textObject;
@@ -695,7 +740,7 @@ void tst_qquicktext::textFormat()
textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->textFormat(), QQuickText::PlainText);
delete textObject;
@@ -723,6 +768,61 @@ void tst_qquicktext::textFormat()
QCOMPARE(text->textFormat(), QQuickText::AutoText);
QCOMPARE(spy.count(), 2);
}
+
+ {
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n Text { text: \"<b>Hello</b>\" }", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickText *text = qobject_cast<QQuickText *>(object.data());
+ QVERIFY(text);
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
+ QVERIFY(textPrivate);
+
+ QCOMPARE(text->textFormat(), QQuickText::AutoText);
+ QVERIFY(!textPrivate->layout.formats().isEmpty());
+
+ text->setTextFormat(QQuickText::StyledText);
+ QVERIFY(!textPrivate->layout.formats().isEmpty());
+
+ text->setTextFormat(QQuickText::PlainText);
+ QVERIFY(textPrivate->layout.formats().isEmpty());
+
+ text->setTextFormat(QQuickText::AutoText);
+ QVERIFY(!textPrivate->layout.formats().isEmpty());
+ }
+
+ {
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nText { text: \"Hello\"; elide: Text.ElideRight }", QUrl::fromLocalFile(""));
+ QScopedPointer<QObject> object(component.create());
+ QQuickText *text = qobject_cast<QQuickText *>(object.data());
+ QVERIFY(text);
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
+ QVERIFY(textPrivate);
+
+ // underline a mnemonic
+ QVector<QTextLayout::FormatRange> formats;
+ QTextLayout::FormatRange range;
+ range.start = 0;
+ range.length = 1;
+ range.format.setFontUnderline(true);
+ formats << range;
+
+ // the mnemonic format should be retained
+ textPrivate->layout.setFormats(formats);
+ text->forceLayout();
+ QCOMPARE(textPrivate->layout.formats(), formats);
+
+ // and carried over to the elide layout
+ text->setWidth(text->implicitWidth() - 1);
+ QVERIFY(textPrivate->elideLayout);
+ QCOMPARE(textPrivate->elideLayout->formats(), formats);
+
+ // but cleared when the text changes
+ text->setText("Changed");
+ QVERIFY(textPrivate->elideLayout);
+ QVERIFY(textPrivate->layout.formats().isEmpty());
+ }
}
//the alignment tests may be trivial o.oa
@@ -766,11 +866,11 @@ void tst_qquicktext::horizontalAlignment_RightToLeft()
{
QScopedPointer<QQuickView> window(createView(testFile("horizontalAlignment_RightToLeft.qml")));
QQuickText *text = window->rootObject()->findChild<QQuickText*>("text");
- QVERIFY(text != 0);
+ QVERIFY(text != nullptr);
window->showNormal();
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QTRY_VERIFY(textPrivate->layout.lineCount());
@@ -903,17 +1003,17 @@ static inline QByteArray msgNotLessThan(int n1, int n2)
void tst_qquicktext::hAlignImplicitWidth()
{
-#if defined(QT_OPENGL_ES_2_ANGLE) && _MSC_VER==1600
- QSKIP("QTBUG-40658");
+#ifdef Q_OS_MACOS
+ QSKIP("this test currently crashes on MacOS. See QTBUG-68047");
#endif
QQuickView view(testFileUrl("hAlignImplicitWidth.qml"));
view.setFlags(view.flags() | Qt::WindowStaysOnTopHint); // Prevent being obscured by other windows.
view.show();
view.requestActivate();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem");
- QVERIFY(text != 0);
+ QVERIFY(text != nullptr);
// Try to check whether alignment works by checking the number of black
// pixels in the thirds of the grabbed image.
@@ -929,6 +1029,10 @@ void tst_qquicktext::hAlignImplicitWidth()
const int centeredSection3End = centeredSection3 + sectionWidth;
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
// Left Align
QImage image = view.grabWindow();
const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image);
@@ -976,7 +1080,7 @@ void tst_qquicktext::verticalAlignment()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
delete textObject;
@@ -992,7 +1096,7 @@ void tst_qquicktext::verticalAlignment()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
delete textObject;
@@ -1388,7 +1492,7 @@ void tst_qquicktext::weight()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().weight(), (int)QQuickFontValueType::Normal);
delete textObject;
@@ -1399,7 +1503,7 @@ void tst_qquicktext::weight()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().weight(), (int)QQuickFontValueType::Bold);
delete textObject;
@@ -1413,7 +1517,7 @@ void tst_qquicktext::underline()
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().overline(), false);
QCOMPARE(textObject->font().underline(), true);
QCOMPARE(textObject->font().strikeOut(), false);
@@ -1426,7 +1530,7 @@ void tst_qquicktext::overline()
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().overline(), true);
QCOMPARE(textObject->font().underline(), false);
QCOMPARE(textObject->font().strikeOut(), false);
@@ -1439,7 +1543,7 @@ void tst_qquicktext::strikeout()
view.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickText *textObject = view.rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().overline(), false);
QCOMPARE(textObject->font().underline(), false);
QCOMPARE(textObject->font().strikeOut(), true);
@@ -1453,7 +1557,7 @@ void tst_qquicktext::capitalization()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::MixedCase);
delete textObject;
@@ -1464,7 +1568,7 @@ void tst_qquicktext::capitalization()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::AllUppercase);
delete textObject;
@@ -1475,7 +1579,7 @@ void tst_qquicktext::capitalization()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::AllLowercase);
delete textObject;
@@ -1486,7 +1590,7 @@ void tst_qquicktext::capitalization()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::SmallCaps);
delete textObject;
@@ -1497,7 +1601,7 @@ void tst_qquicktext::capitalization()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().capitalization(), (int)QQuickFontValueType::Capitalize);
delete textObject;
@@ -1512,7 +1616,7 @@ void tst_qquicktext::letterSpacing()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().letterSpacing(), 0.0);
delete textObject;
@@ -1523,7 +1627,7 @@ void tst_qquicktext::letterSpacing()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().letterSpacing(), -2.);
delete textObject;
@@ -1534,7 +1638,7 @@ void tst_qquicktext::letterSpacing()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().letterSpacing(), 3.);
delete textObject;
@@ -1549,7 +1653,7 @@ void tst_qquicktext::wordSpacing()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().wordSpacing(), 0.0);
delete textObject;
@@ -1560,7 +1664,7 @@ void tst_qquicktext::wordSpacing()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().wordSpacing(), -50.);
delete textObject;
@@ -1571,7 +1675,7 @@ void tst_qquicktext::wordSpacing()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->font().wordSpacing(), 200.);
delete textObject;
@@ -1968,7 +2072,7 @@ void tst_qquicktext::linkInteraction()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
LinkTest test;
QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString)));
@@ -2090,7 +2194,7 @@ void tst_qquicktext::embeddedImages()
QVERIFY(QTest::qWaitForWindowActive(view));
QQuickText *textObject = qobject_cast<QQuickText*>(view->rootObject());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QTRY_COMPARE(textObject->resourcesLoading(), 0);
QPixmap pm(testFile("http/exists.png"));
@@ -2111,7 +2215,7 @@ void tst_qquicktext::lineCount()
QScopedPointer<QQuickView> window(createView(testFile("lineCount.qml")));
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
QVERIFY(myText->lineCount() > 1);
QVERIFY(!myText->truncated());
@@ -2138,7 +2242,7 @@ void tst_qquicktext::lineHeight()
QScopedPointer<QQuickView> window(createView(testFile("lineHeight.qml")));
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
QCOMPARE(myText->lineHeight(), qreal(1));
QCOMPARE(myText->lineHeightMode(), QQuickText::ProportionalHeight);
@@ -2283,23 +2387,31 @@ void tst_qquicktext::contentSize()
QScopedPointer<QObject> object(textComponent.create());
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
- QSignalSpy spy(textObject, SIGNAL(contentSizeChanged()));
+ QSignalSpy spySize(textObject, SIGNAL(contentSizeChanged()));
+ QSignalSpy spyWidth(textObject, SIGNAL(contentWidthChanged(qreal)));
+ QSignalSpy spyHeight(textObject, SIGNAL(contentHeightChanged(qreal)));
textObject->setText("The quick red fox jumped over the lazy brown dog");
QVERIFY(textObject->contentWidth() > textObject->width());
QVERIFY(textObject->contentHeight() < textObject->height());
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spySize.count(), 1);
+ QCOMPARE(spyWidth.count(), 1);
+ QCOMPARE(spyHeight.count(), 0);
textObject->setWrapMode(QQuickText::WordWrap);
QVERIFY(textObject->contentWidth() <= textObject->width());
QVERIFY(textObject->contentHeight() > textObject->height());
- QCOMPARE(spy.count(), 2);
+ QCOMPARE(spySize.count(), 2);
+ QCOMPARE(spyWidth.count(), 2);
+ QCOMPARE(spyHeight.count(), 1);
textObject->setElideMode(QQuickText::ElideRight);
QVERIFY(textObject->contentWidth() <= textObject->width());
QVERIFY(textObject->contentHeight() < textObject->height());
- QCOMPARE(spy.count(), 3);
+ QCOMPARE(spySize.count(), 3);
+ QCOMPARE(spyWidth.count(), 3);
+ QCOMPARE(spyHeight.count(), 2);
int spyCount = 3;
qreal elidedWidth = textObject->contentWidth();
@@ -2308,14 +2420,16 @@ void tst_qquicktext::contentSize()
QVERIFY(textObject->contentHeight() < textObject->height());
// this text probably won't have the same elided width, but it's not guaranteed.
if (textObject->contentWidth() != elidedWidth)
- QCOMPARE(spy.count(), ++spyCount);
+ QCOMPARE(spySize.count(), ++spyCount);
else
- QCOMPARE(spy.count(), spyCount);
+ QCOMPARE(spySize.count(), spyCount);
textObject->setElideMode(QQuickText::ElideNone);
QVERIFY(textObject->contentWidth() > textObject->width());
QVERIFY(textObject->contentHeight() > textObject->height());
- QCOMPARE(spy.count(), ++spyCount);
+ QCOMPARE(spySize.count(), ++spyCount);
+ QCOMPARE(spyWidth.count(), spyCount);
+ QCOMPARE(spyHeight.count(), 3);
}
void tst_qquicktext::geometryChanged()
@@ -2736,10 +2850,10 @@ void tst_qquicktext::lineLaidOut()
QScopedPointer<QQuickView> window(createView(testFile("lineLayout.qml")));
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QVERIFY(!textPrivate->extra.isAllocated());
@@ -2764,10 +2878,10 @@ void tst_qquicktext::lineLaidOutRelayout()
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QVERIFY(!textPrivate->extra.isAllocated());
@@ -2792,10 +2906,10 @@ void tst_qquicktext::lineLaidOutHAlign()
QScopedPointer<QQuickView> window(createView(testFile("lineLayoutHAlign.qml")));
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QCOMPARE(textPrivate->layout.lineCount(), 1);
@@ -2922,11 +3036,11 @@ void tst_qquicktext::imgTagsAlign()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("."));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->height(), qreal(imgHeight));
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QRectF br = textPrivate->layout.boundingRect();
if (align == "bottom")
@@ -2947,11 +3061,11 @@ void tst_qquicktext::imgTagsMultipleImages()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("."));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->height(), qreal(85));
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QCOMPARE(textPrivate->extra->visibleImgTags.count(), 2);
delete textObject;
@@ -2961,10 +3075,10 @@ void tst_qquicktext::imgTagsElide()
{
QScopedPointer<QQuickView> window(createView(testFile("imgTagsElide.qml")));
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QCOMPARE(textPrivate->extra->visibleImgTags.count(), 0);
myText->setMaximumLineCount(20);
QTRY_COMPARE(textPrivate->extra->visibleImgTags.count(), 1);
@@ -2976,12 +3090,12 @@ void tst_qquicktext::imgTagsUpdates()
{
QScopedPointer<QQuickView> window(createView(testFile("imgTagsUpdates.qml")));
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
QSignalSpy spy(myText, SIGNAL(contentSizeChanged()));
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
myText->setText("This is a heart<img src=\"images/heart200.png\">.");
QCOMPARE(textPrivate->extra->visibleImgTags.count(), 1);
@@ -3007,7 +3121,7 @@ void tst_qquicktext::imgTagsError()
textComponent.setData(componentStr.toLatin1(), QUrl("file:"));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
delete textObject;
}
@@ -3026,10 +3140,10 @@ void tst_qquicktext::fontSizeMode()
window->show();
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
myText->setText(text);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
qreal originalWidth = myText->contentWidth();
qreal originalHeight = myText->contentHeight();
@@ -3043,7 +3157,7 @@ void tst_qquicktext::fontSizeMode()
myText->setFont(font);
myText->setFontSizeMode(QQuickText::HorizontalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Font size reduced to fit within the width of the item.
qreal horizontalFitWidth = myText->contentWidth();
qreal horizontalFitHeight = myText->contentHeight();
@@ -3052,28 +3166,28 @@ void tst_qquicktext::fontSizeMode()
// Elide won't affect the size with HorizontalFit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideLeft);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideMiddle);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::VerticalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Font size increased to fill the height of the item.
qreal verticalFitHeight = myText->contentHeight();
QVERIFY(myText->contentWidth() > myText->width());
@@ -3082,57 +3196,57 @@ void tst_qquicktext::fontSizeMode()
// Elide won't affect the height of a single line with VerticalFit but will crop the width.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(myText->truncated());
QVERIFY(myText->contentWidth() <= myText->width() + 2);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideLeft);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(myText->truncated());
QVERIFY(myText->contentWidth() <= myText->width() + 2);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideMiddle);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(myText->truncated());
QVERIFY(myText->contentWidth() <= myText->width() + 2);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::Fit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Should be the same as HorizontalFit with no wrapping.
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
// Elide won't affect the size with Fit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideLeft);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideMiddle);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::FixedSize);
myText->setWrapMode(QQuickText::Wrap);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
originalWidth = myText->contentWidth();
originalHeight = myText->contentHeight();
@@ -3142,7 +3256,7 @@ void tst_qquicktext::fontSizeMode()
QVERIFY(originalHeight > myText->height());
myText->setFontSizeMode(QQuickText::HorizontalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
// same size as without text wrapping.
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
@@ -3150,16 +3264,16 @@ void tst_qquicktext::fontSizeMode()
// Elide won't affect the size with HorizontalFit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::VerticalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// VerticalFit should reduce the size to the wrapped text within the vertical height.
verticalFitHeight = myText->contentHeight();
qreal verticalFitWidth = myText->contentWidth();
@@ -3169,40 +3283,40 @@ void tst_qquicktext::fontSizeMode()
// Elide won't affect the height or width of a wrapped text with VerticalFit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::Fit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Should be the same as VerticalFit with wrapping.
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
// Elide won't affect the size with Fit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::FixedSize);
myText->setMaximumLineCount(2);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// The original text wrapped should exceed the height of the item.
QVERIFY(originalWidth <= myText->width() + 2);
QVERIFY(originalHeight > myText->height());
myText->setFontSizeMode(QQuickText::HorizontalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
// same size as without text wrapping.
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
@@ -3210,16 +3324,16 @@ void tst_qquicktext::fontSizeMode()
// Elide won't affect the size with HorizontalFit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::VerticalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// VerticalFit should reduce the size to the wrapped text within the vertical height.
verticalFitHeight = myText->contentHeight();
verticalFitWidth = myText->contentWidth();
@@ -3229,29 +3343,29 @@ void tst_qquicktext::fontSizeMode()
// Elide won't affect the height or width of a wrapped text with VerticalFit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::Fit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Should be the same as VerticalFit with wrapping.
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
// Elide won't affect the size with Fit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
}
void tst_qquicktext::fontSizeModeMultiline_data()
@@ -3269,10 +3383,10 @@ void tst_qquicktext::fontSizeModeMultiline()
window->show();
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
myText->setText(text);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
qreal originalWidth = myText->contentWidth();
qreal originalHeight = myText->contentHeight();
@@ -3287,7 +3401,7 @@ void tst_qquicktext::fontSizeModeMultiline()
myText->setFont(font);
myText->setFontSizeMode(QQuickText::HorizontalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Font size reduced to fit within the width of the item.
QCOMPARE(myText->lineCount(), 2);
qreal horizontalFitWidth = myText->contentWidth();
@@ -3297,7 +3411,7 @@ void tst_qquicktext::fontSizeModeMultiline()
// Right eliding will remove the last line
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(myText->truncated());
QCOMPARE(myText->lineCount(), 1);
QVERIFY(myText->contentWidth() <= myText->width() + 2);
@@ -3305,22 +3419,22 @@ void tst_qquicktext::fontSizeModeMultiline()
// Left or middle eliding wont have any effect.
myText->setElideMode(QQuickText::ElideLeft);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideMiddle);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
QCOMPARE(myText->contentHeight(), horizontalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::VerticalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Font size reduced to fit within the height of the item.
qreal verticalFitWidth = myText->contentWidth();
qreal verticalFitHeight = myText->contentHeight();
@@ -3329,58 +3443,58 @@ void tst_qquicktext::fontSizeModeMultiline()
// Elide will have no effect.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QVERIFY(myText->contentWidth() <= myText->width() + 2);
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideLeft);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideMiddle);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::Fit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Should be the same as VerticalFit with no wrapping.
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
// Elide won't affect the size with Fit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideLeft);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideMiddle);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::FixedSize);
myText->setWrapMode(QQuickText::Wrap);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
originalWidth = myText->contentWidth();
originalHeight = myText->contentHeight();
@@ -3390,7 +3504,7 @@ void tst_qquicktext::fontSizeModeMultiline()
QVERIFY(originalHeight > myText->height());
myText->setFontSizeMode(QQuickText::HorizontalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
// same size as without text wrapping.
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
@@ -3398,16 +3512,16 @@ void tst_qquicktext::fontSizeModeMultiline()
// Text will be elided vertically with HorizontalFit
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(myText->truncated());
QVERIFY(myText->contentWidth() <= myText->width() + 2);
QVERIFY(myText->contentHeight() <= myText->height() + 2);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::VerticalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// VerticalFit should reduce the size to the wrapped text within the vertical height.
verticalFitHeight = myText->contentHeight();
verticalFitWidth = myText->contentWidth();
@@ -3417,40 +3531,40 @@ void tst_qquicktext::fontSizeModeMultiline()
// Elide won't affect the height or width of a wrapped text with VerticalFit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::Fit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Should be the same as VerticalFit with wrapping.
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
// Elide won't affect the size with Fit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::FixedSize);
myText->setMaximumLineCount(2);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// The original text wrapped should exceed the height of the item.
QVERIFY(originalWidth <= myText->width() + 2);
QVERIFY(originalHeight > myText->height());
myText->setFontSizeMode(QQuickText::HorizontalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
// same size as without text wrapping.
QCOMPARE(myText->contentWidth(), horizontalFitWidth);
@@ -3458,16 +3572,16 @@ void tst_qquicktext::fontSizeModeMultiline()
// Elide won't affect the size with HorizontalFit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(myText->truncated());
QVERIFY(myText->contentWidth() <= myText->width() + 2);
QVERIFY(myText->contentHeight() <= myText->height() + 2);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::VerticalFit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// VerticalFit should reduce the size to the wrapped text within the vertical height.
verticalFitHeight = myText->contentHeight();
verticalFitWidth = myText->contentWidth();
@@ -3477,29 +3591,29 @@ void tst_qquicktext::fontSizeModeMultiline()
// Elide won't affect the height or width of a wrapped text with VerticalFit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
myText->setFontSizeMode(QQuickText::Fit);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
// Should be the same as VerticalFit with wrapping.
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
// Elide won't affect the size with Fit.
myText->setElideMode(QQuickText::ElideRight);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QVERIFY(!myText->truncated());
QCOMPARE(myText->contentWidth(), verticalFitWidth);
QCOMPARE(myText->contentHeight(), verticalFitHeight);
myText->setElideMode(QQuickText::ElideNone);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
}
void tst_qquicktext::multilengthStrings_data()
@@ -3517,24 +3631,24 @@ void tst_qquicktext::multilengthStrings()
window->show();
QQuickText *myText = window->rootObject()->findChild<QQuickText*>("myText");
- QVERIFY(myText != 0);
+ QVERIFY(myText != nullptr);
const QString longText = "the quick brown fox jumped over the lazy dog";
const QString mediumText = "the brown fox jumped over the dog";
const QString shortText = "fox jumped dog";
myText->setText(longText);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
const qreal longWidth = myText->contentWidth();
const qreal longHeight = myText->contentHeight();
myText->setText(mediumText);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
const qreal mediumWidth = myText->contentWidth();
const qreal mediumHeight = myText->contentHeight();
myText->setText(shortText);
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
const qreal shortWidth = myText->contentWidth();
const qreal shortHeight = myText->contentHeight();
@@ -3542,21 +3656,21 @@ void tst_qquicktext::multilengthStrings()
myText->setText(longText + QLatin1Char('\x9c') + mediumText + QLatin1Char('\x9c') + shortText);
myText->setSize(QSizeF(longWidth, longHeight));
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QCOMPARE(myText->contentWidth(), longWidth);
QCOMPARE(myText->contentHeight(), longHeight);
QCOMPARE(myText->truncated(), false);
myText->setSize(QSizeF(mediumWidth, mediumHeight));
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QCOMPARE(myText->contentWidth(), mediumWidth);
QCOMPARE(myText->contentHeight(), mediumHeight);
QCOMPARE(myText->truncated(), true);
myText->setSize(QSizeF(shortWidth, shortHeight));
- QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
+ QVERIFY(QQuickTest::qWaitForItemPolished(myText));
QCOMPARE(myText->contentWidth(), shortWidth);
QCOMPARE(myText->contentHeight(), shortHeight);
@@ -3597,8 +3711,8 @@ void tst_qquicktext::fontFormatSizes()
QQuickText *qtext = view->rootObject()->findChild<QQuickText*>("text");
QQuickText *qtextWithTag = view->rootObject()->findChild<QQuickText*>("textWithTag");
- QVERIFY(qtext != 0);
- QVERIFY(qtextWithTag != 0);
+ QVERIFY(qtext != nullptr);
+ QVERIFY(qtextWithTag != nullptr);
qtext->setText(text);
qtextWithTag->setText(textWithTag);
@@ -3616,8 +3730,8 @@ void tst_qquicktext::fontFormatSizes()
view->setSource(testFileUrl("pixelFontSizes.qml"));
QQuickText *qtext = view->rootObject()->findChild<QQuickText*>("text");
QQuickText *qtextWithTag = view->rootObject()->findChild<QQuickText*>("textWithTag");
- QVERIFY(qtext != 0);
- QVERIFY(qtextWithTag != 0);
+ QVERIFY(qtext != nullptr);
+ QVERIFY(qtextWithTag != nullptr);
qtext->setText(text);
qtextWithTag->setText(textWithTag);
@@ -3983,10 +4097,10 @@ void tst_qquicktext::htmlLists()
QQuickText *textObject = view->rootObject()->findChild<QQuickText*>("myText");
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
- QVERIFY(textPrivate != 0);
+ QVERIFY(textPrivate != nullptr);
QVERIFY(textPrivate->extra.isAllocated());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
textObject->setText(text);
view->show();
@@ -4083,7 +4197,7 @@ void tst_qquicktext::padding()
QQuickItem *root = window->rootObject();
QVERIFY(root);
QQuickText *obj = qobject_cast<QQuickText*>(root);
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
qreal cw = obj->contentWidth();
qreal ch = obj->contentHeight();
@@ -4171,7 +4285,7 @@ void tst_qquicktext::hintingPreference()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().hintingPreference(), (int)QFont::PreferDefaultHinting);
delete textObject;
@@ -4182,7 +4296,7 @@ void tst_qquicktext::hintingPreference()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE((int)textObject->font().hintingPreference(), (int)QFont::PreferNoHinting);
delete textObject;
@@ -4272,6 +4386,35 @@ void tst_qquicktext::fontInfo()
QVERIFY(copy->font().pixelSize() < 1000);
}
+void tst_qquicktext::initialContentHeight()
+{
+ QQmlComponent component(&engine, testFile("contentHeight.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> object(component.create());
+ QObject *root = object.data();
+ QVERIFY(root);
+ QQuickText *text = qobject_cast<QQuickText *>(root);
+ QVERIFY(text);
+ QCOMPARE(text->height(), text->contentHeight());
+}
+
+void tst_qquicktext::implicitSizeChangeRewrap()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("implicitSizeChangeRewrap.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QObject *root = window->rootObject();
+
+ QQuickText *text = root->findChild<QQuickText *>("text");
+ QVERIFY(text != nullptr);
+
+ QVERIFY(text->contentWidth() < window->width());
+}
+
QTEST_MAIN(tst_qquicktext)
#include "tst_qquicktext.moc"
diff --git a/tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp b/tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp
index 7507938589..e9c699db6a 100644
--- a/tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp
+++ b/tests/auto/quick/qquicktextdocument/tst_qquicktextdocument.cpp
@@ -58,7 +58,7 @@ void tst_qquicktextdocument::textDocumentWriter()
QVERIFY(edit);
QQuickTextDocument* quickDocument = qobject_cast<QQuickTextDocument*>(edit->property("textDocument").value<QObject*>());
- QVERIFY(quickDocument->textDocument() != 0);
+ QVERIFY(quickDocument->textDocument() != nullptr);
QBuffer output;
output.open(QBuffer::ReadWrite);
@@ -73,7 +73,7 @@ void tst_qquicktextdocument::textDocumentWriter()
void tst_qquicktextdocument::textDocumentWithImage()
{
- QQuickTextDocumentWithImageResources document(0);
+ QQuickTextDocumentWithImageResources document(nullptr);
QImage image(1, 1, QImage::Format_Mono);
image.fill(1);
diff --git a/tests/auto/quick/qquicktextedit/data/keys_shortcutoverride.qml b/tests/auto/quick/qquicktextedit/data/keys_shortcutoverride.qml
new file mode 100644
index 0000000000..24bd434830
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/keys_shortcutoverride.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.10
+
+Item {
+ width: 320
+ height: 200
+ property string who : "nobody"
+
+ Shortcut {
+ sequence: "Esc"
+ onActivated: who = "Shortcut"
+ }
+
+ TextEdit {
+ id: txt
+ x: 100
+ text: "enter text"
+ Keys.onShortcutOverride: {
+ who = "TextEdit"
+ event.accepted = (event.key === Qt.Key_Escape)
+ }
+ }
+
+ Rectangle {
+ objectName: "rectangle"
+ width: 90
+ height: width
+ focus: true
+ color: focus ? "red" : "gray"
+ Keys.onShortcutOverride: {
+ who = "Rectangle"
+ event.accepted = (event.key === Qt.Key_Escape)
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index ac57a05176..ce2a8eb257 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -36,6 +36,7 @@
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlcomponent.h>
#include <QtGui/qguiapplication.h>
+#include <private/qquickrectangle_p.h>
#include <private/qquicktextedit_p.h>
#include <private/qquicktextedit_p_p.h>
#include <private/qquicktext_p.h>
@@ -158,6 +159,7 @@ private slots:
#endif
void implicitSize_data();
void implicitSize();
+ void implicitSize_QTBUG_63153();
void contentSize();
void boundingRect();
void clipRect();
@@ -204,12 +206,13 @@ private slots:
void padding();
void QTBUG_51115_readOnlyResetsSelection();
+ void keys_shortcutoverride();
private:
void simulateKeys(QWindow *window, const QList<Key> &keys);
void simulateKeys(QWindow *window, const QKeySequence &sequence);
- void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = 0);
+ void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = nullptr);
QStringList standard;
QStringList richText;
@@ -335,7 +338,7 @@ void tst_qquicktextedit::cleanup()
{
// ensure not even skipped tests with custom input context leave it dangling
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
- inputMethodPrivate->testContext = 0;
+ inputMethodPrivate->testContext = nullptr;
}
void tst_qquicktextedit::text()
@@ -345,7 +348,7 @@ void tst_qquicktextedit::text()
texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\" }", QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->text(), QString(""));
QCOMPARE(textEditObject->length(), 0);
}
@@ -357,7 +360,7 @@ void tst_qquicktextedit::text()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->text(), standard.at(i));
QCOMPARE(textEditObject->length(), standard.at(i).length());
}
@@ -370,7 +373,7 @@ void tst_qquicktextedit::text()
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QString expected = richText.at(i);
expected.replace(QRegExp("\\\\(.)"),"\\1");
@@ -385,7 +388,7 @@ void tst_qquicktextedit::text()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QString actual = textEditObject->text();
QString expected = standard.at(i);
@@ -403,7 +406,7 @@ void tst_qquicktextedit::text()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QString actual = textEditObject->text();
QString expected = richText.at(i);
actual.replace(QRegExp(".*<body[^>]*>"),"");
@@ -422,7 +425,7 @@ void tst_qquicktextedit::text()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->text(), standard.at(i));
QCOMPARE(textEditObject->length(), standard.at(i).length());
}
@@ -434,7 +437,7 @@ void tst_qquicktextedit::text()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QString actual = textEditObject->text();
QString expected = richText.at(i);
actual.replace(QRegExp(".*<body[^>]*>"),"");
@@ -455,7 +458,7 @@ void tst_qquicktextedit::width()
texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\" }", QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->width(), 0.0);
}
@@ -491,7 +494,7 @@ void tst_qquicktextedit::width()
qreal metricWidth = layout.boundingRect().width();
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->width(), metricWidth);
}
@@ -510,7 +513,7 @@ void tst_qquicktextedit::width()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->width(), documentWidth);
}
}
@@ -523,7 +526,7 @@ void tst_qquicktextedit::wrap()
texteditComponent.setData("import QtQuick 2.0\nTextEdit { text: \"\"; wrapMode: TextEdit.WordWrap; width: 300 }", QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->width(), 300.);
}
@@ -534,7 +537,7 @@ void tst_qquicktextedit::wrap()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->width(), 300.);
}
@@ -545,7 +548,7 @@ void tst_qquicktextedit::wrap()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->width(), 300.);
}
{
@@ -580,7 +583,7 @@ void tst_qquicktextedit::textFormat()
textComponent.setData("import QtQuick 2.0\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->textFormat(), QQuickTextEdit::RichText);
}
{
@@ -588,7 +591,7 @@ void tst_qquicktextedit::textFormat()
textComponent.setData("import QtQuick 2.0\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->textFormat(), QQuickTextEdit::PlainText);
}
{
@@ -678,7 +681,7 @@ void tst_qquicktextedit::hAlign()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
}
}
@@ -692,7 +695,7 @@ void tst_qquicktextedit::hAlign()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
}
}
@@ -707,7 +710,7 @@ void tst_qquicktextedit::hAlign_RightToLeft()
QQuickView window(testFileUrl("horizontalAlignment_RightToLeft.qml"));
QQuickTextEdit *textEdit = window.rootObject()->findChild<QQuickTextEdit*>("text");
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
window.showNormal();
const QString rtlText = textEdit->text();
@@ -789,7 +792,7 @@ void tst_qquicktextedit::hAlign_RightToLeft()
QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
textEdit->setText(QString());
@@ -852,7 +855,7 @@ void tst_qquicktextedit::hAlign_RightToLeft()
// make sure editor doesn't rely on input for updating size
QQuickTextEdit *emptyEdit = window.rootObject()->findChild<QQuickTextEdit*>("emptyTextEdit");
- QVERIFY(emptyEdit != 0);
+ QVERIFY(emptyEdit != nullptr);
platformInputContext.setInputDirection(Qt::RightToLeft);
emptyEdit->setFocus(true);
QCOMPARE(emptyEdit->hAlign(), QQuickTextEdit::AlignRight);
@@ -890,7 +893,7 @@ void tst_qquicktextedit::hAlignVisual()
QVERIFY(QTest::qWaitForWindowExposed(&view));
QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem");
- QVERIFY(text != 0);
+ QVERIFY(text != nullptr);
// Try to check whether alignment works by checking the number of black
// pixels in the thirds of the grabbed image.
@@ -904,6 +907,10 @@ void tst_qquicktextedit::hAlignVisual()
const int centeredSection3End = centeredSection3 + sectionWidth;
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
// Left Align
QImage image = view.grabWindow();
const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image);
@@ -982,7 +989,7 @@ void tst_qquicktextedit::vAlign()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
}
}
@@ -996,7 +1003,7 @@ void tst_qquicktextedit::vAlign()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
}
}
@@ -1007,7 +1014,7 @@ void tst_qquicktextedit::vAlign()
"TextEdit { width: 100; height: 100; text: \"Hello World\" }", QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->vAlign(), QQuickTextEdit::AlignTop);
QVERIFY(textEditObject->cursorRectangle().bottom() < 50);
@@ -1050,7 +1057,7 @@ void tst_qquicktextedit::font()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->font().pointSize(), 40);
QCOMPARE(textEditObject->font().bold(), false);
QCOMPARE(textEditObject->font().italic(), false);
@@ -1062,7 +1069,7 @@ void tst_qquicktextedit::font()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->font().bold(), true);
QCOMPARE(textEditObject->font().italic(), false);
}
@@ -1073,7 +1080,7 @@ void tst_qquicktextedit::font()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->font().italic(), true);
QCOMPARE(textEditObject->font().bold(), false);
}
@@ -1084,7 +1091,7 @@ void tst_qquicktextedit::font()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->font().family(), QString("Helvetica"));
QCOMPARE(textEditObject->font().bold(), false);
QCOMPARE(textEditObject->font().italic(), false);
@@ -1096,7 +1103,7 @@ void tst_qquicktextedit::font()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->font().family(), QString(""));
}
}
@@ -1161,7 +1168,7 @@ void tst_qquicktextedit::color()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
//qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
}
@@ -1172,7 +1179,7 @@ void tst_qquicktextedit::color()
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i)));
}
@@ -1183,7 +1190,7 @@ void tst_qquicktextedit::color()
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i)));
}
@@ -1197,7 +1204,7 @@ void tst_qquicktextedit::color()
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->color(), testColor);
}
}
@@ -1209,7 +1216,7 @@ void tst_qquicktextedit::textMargin()
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->textMargin(), i);
}
}
@@ -1219,7 +1226,7 @@ void tst_qquicktextedit::persistentSelection()
QQuickView window(testFileUrl("persistentSelection.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
QVERIFY(edit);
@@ -1255,6 +1262,34 @@ void tst_qquicktextedit::persistentSelection()
edit->setFocus(true);
QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
+ // QTBUG-50587 (persistentSelection with readOnly)
+ edit->setReadOnly(true);
+
+ edit->setPersistentSelection(false);
+ QCOMPARE(edit->persistentSelection(), false);
+ QCOMPARE(spy.count(), 2);
+
+ edit->select(1, 4);
+ QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
+
+ edit->setFocus(false);
+ QCOMPARE(edit->property("selected").toString(), QString());
+
+ edit->setFocus(true);
+ QCOMPARE(edit->property("selected").toString(), QString());
+
+ edit->setPersistentSelection(true);
+ QCOMPARE(edit->persistentSelection(), true);
+ QCOMPARE(spy.count(), 3);
+
+ edit->select(1, 4);
+ QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
+
+ edit->setFocus(false);
+ QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
+
+ edit->setFocus(true);
+ QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
}
void tst_qquicktextedit::selectionOnFocusOut()
@@ -1262,7 +1297,7 @@ void tst_qquicktextedit::selectionOnFocusOut()
QQuickView window(testFileUrl("focusOutSelection.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QPoint p1(25, 35);
QPoint p2(25, 85);
@@ -1270,14 +1305,14 @@ void tst_qquicktextedit::selectionOnFocusOut()
QQuickTextEdit *edit1 = window.rootObject()->findChild<QQuickTextEdit*>("text1");
QQuickTextEdit *edit2 = window.rootObject()->findChild<QQuickTextEdit*>("text2");
- QTest::mouseClick(&window, Qt::LeftButton, 0, p1);
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
QVERIFY(edit1->hasActiveFocus());
QVERIFY(!edit2->hasActiveFocus());
edit1->selectAll();
QCOMPARE(edit1->selectedText(), QLatin1String("text 1"));
- QTest::mouseClick(&window, Qt::LeftButton, 0, p2);
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p2);
QCOMPARE(edit1->selectedText(), QLatin1String(""));
QVERIFY(!edit1->hasActiveFocus());
@@ -1313,7 +1348,7 @@ void tst_qquicktextedit::focusOnPress()
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QCOMPARE(textEditObject->focusOnPress(), true);
QCOMPARE(textEditObject->hasFocus(), false);
@@ -1330,13 +1365,13 @@ void tst_qquicktextedit::focusOnPress()
textEditObject->setParentItem(window.contentItem());
window.showNormal();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(textEditObject->hasFocus(), false);
QCOMPARE(textEditObject->hasActiveFocus(), false);
QPoint centerPoint(window.width()/2, window.height()/2);
- Qt::KeyboardModifiers noModifiers = 0;
+ Qt::KeyboardModifiers noModifiers = nullptr;
QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), true);
@@ -1391,7 +1426,7 @@ void tst_qquicktextedit::selection()
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
//Test selection follows cursor
@@ -1474,7 +1509,7 @@ void tst_qquicktextedit::overwriteMode()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
QSignalSpy spy(textEdit, SIGNAL(overwriteModeChanged(bool)));
@@ -1482,7 +1517,7 @@ void tst_qquicktextedit::overwriteMode()
textEdit->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
@@ -1598,13 +1633,13 @@ void tst_qquicktextedit::keySelection()
QQuickView window(testFileUrl("navigation.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
- QVERIFY(input != 0);
+ QVERIFY(input != nullptr);
QVERIFY(input->hasActiveFocus());
QSignalSpy spy(input, SIGNAL(selectedTextChanged()));
@@ -1800,7 +1835,7 @@ void tst_qquicktextedit::moveCursorSelection()
QQmlComponent textinputComponent(&engine);
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit*>(textinputComponent.create());
- QVERIFY(texteditObject != 0);
+ QVERIFY(texteditObject != nullptr);
texteditObject->setCursorPosition(cursorPosition);
texteditObject->moveCursorSelection(movePosition, mode);
@@ -1959,7 +1994,7 @@ void tst_qquicktextedit::moveCursorSelectionSequence()
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
- QVERIFY(texteditObject != 0);
+ QVERIFY(texteditObject != nullptr);
texteditObject->setCursorPosition(cursorPosition);
@@ -2055,11 +2090,11 @@ void tst_qquicktextedit::mouseSelection()
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
textEditObject->setFocus(focus);
textEditObject->setFocusOnPress(focusOnPress);
@@ -2102,19 +2137,19 @@ void tst_qquicktextedit::dragMouseSelection()
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
// press-and-drag-and-release from x1 to x2
int x1 = 10;
int x2 = 70;
int y = QFontMetrics(textEditObject->font()).height() / 2;
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x1,y));
QTest::mouseMove(&window, QPoint(x2, y));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x2,y));
QTest::qWait(300);
QString str1;
QTRY_VERIFY((str1 = textEditObject->selectedText()).length() > 3);
@@ -2122,9 +2157,9 @@ void tst_qquicktextedit::dragMouseSelection()
// press and drag the current selection.
x1 = 40;
x2 = 100;
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x1,y));
QTest::mouseMove(&window, QPoint(x2, y));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x2,y));
QTest::qWait(300);
QString str2;
QTRY_VERIFY((str2 = textEditObject->selectedText()).length() > 3);
@@ -2155,19 +2190,19 @@ void tst_qquicktextedit::mouseSelectionMode()
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
// press-and-drag-and-release from x1 to x2
int x1 = 10;
int x2 = 70;
int y = textEditObject->height()/2;
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x1,y));
QTest::mouseMove(&window, QPoint(x2, y));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x2,y));
QString str = textEditObject->selectedText();
if (selectWords) {
QTRY_COMPARE(textEditObject->selectedText(), text);
@@ -2340,7 +2375,7 @@ void tst_qquicktextedit::keyboardSelection()
edit->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(edit->hasActiveFocus());
simulateKeys(&window, standardKey);
@@ -2378,9 +2413,9 @@ void tst_qquicktextedit::inputMethodHints()
window.show();
window.requestActivate();
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
QSignalSpy inputMethodHintSpy(textEditObject, SIGNAL(inputMethodHintsChanged()));
textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
@@ -2414,13 +2449,13 @@ void tst_qquicktextedit::positionAt()
QFETCH(QQuickTextEdit::VAlignment, verticalAlignment);
QQuickView window(testFileUrl("positionAt.qml"));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QVERIFY(texteditObject != 0);
+ QVERIFY(texteditObject != nullptr);
texteditObject->setHAlign(horizontalAlignment);
texteditObject->setVAlign(verticalAlignment);
@@ -2504,13 +2539,13 @@ void tst_qquicktextedit::positionAt()
void tst_qquicktextedit::linkInteraction()
{
QQuickView window(testFileUrl("linkInteraction.qml"));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QVERIFY(texteditObject != 0);
+ QVERIFY(texteditObject != nullptr);
QSignalSpy spy(texteditObject, SIGNAL(linkActivated(QString)));
QSignalSpy hover(texteditObject, SIGNAL(linkHovered(QString)));
@@ -2520,7 +2555,7 @@ void tst_qquicktextedit::linkInteraction()
const QPointF linkPos = texteditObject->positionToRectangle(7).center();
const QPointF textPos = texteditObject->positionToRectangle(2).center();
- QTest::mouseClick(&window, Qt::LeftButton, 0, linkPos.toPoint());
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, linkPos.toPoint());
QTRY_COMPARE(spy.count(), 1);
QTRY_COMPARE(hover.count(), 1);
QCOMPARE(spy.last()[0].toString(), link);
@@ -2528,7 +2563,7 @@ void tst_qquicktextedit::linkInteraction()
QCOMPARE(texteditObject->hoveredLink(), link);
QCOMPARE(texteditObject->linkAt(linkPos.x(), linkPos.y()), link);
- QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint());
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, textPos.toPoint());
QTRY_COMPARE(spy.count(), 1);
QTRY_COMPARE(hover.count(), 2);
QCOMPARE(hover.last()[0].toString(), QString());
@@ -2537,7 +2572,7 @@ void tst_qquicktextedit::linkInteraction()
texteditObject->setReadOnly(true);
- QTest::mouseClick(&window, Qt::LeftButton, 0, linkPos.toPoint());
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, linkPos.toPoint());
QTRY_COMPARE(spy.count(), 2);
QTRY_COMPARE(hover.count(), 3);
QCOMPARE(spy.last()[0].toString(), link);
@@ -2545,7 +2580,7 @@ void tst_qquicktextedit::linkInteraction()
QCOMPARE(texteditObject->hoveredLink(), link);
QCOMPARE(texteditObject->linkAt(linkPos.x(), linkPos.y()), link);
- QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint());
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, textPos.toPoint());
QTRY_COMPARE(spy.count(), 2);
QTRY_COMPARE(hover.count(), 4);
QCOMPARE(hover.last()[0].toString(), QString());
@@ -2567,9 +2602,9 @@ void tst_qquicktextedit::cursorDelegate()
QQuickView view(source);
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
// Delegate creation is deferred until focus in or cursor visibility is forced.
QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
QVERIFY(!textEditObject->isCursorVisible());
@@ -2591,7 +2626,7 @@ void tst_qquicktextedit::cursorDelegate()
textEditObject->setCursorPosition(0);
const QPoint point1 = textEditObject->positionToRectangle(5).center().toPoint();
QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, 0, point1);
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, point1);
QTest::qWait(50);
QTRY_VERIFY(textEditObject->cursorPosition() != 0);
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
@@ -2601,10 +2636,10 @@ void tst_qquicktextedit::cursorDelegate()
textEditObject->setCursorPosition(0);
const QPoint point2 = textEditObject->positionToRectangle(10).center().toPoint();
QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mousePress(&view, Qt::LeftButton, 0, point1);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, point1);
QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
QGuiApplication::sendEvent(&view, &mv);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, point2);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, point2);
QTest::qWait(50);
QTRY_COMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
@@ -2612,7 +2647,7 @@ void tst_qquicktextedit::cursorDelegate()
textEditObject->setReadOnly(true);
textEditObject->setCursorPosition(0);
QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, textEditObject->positionToRectangle(5).center().toPoint());
QTest::qWait(50);
QTRY_VERIFY(textEditObject->cursorPosition() != 0);
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
@@ -2620,7 +2655,7 @@ void tst_qquicktextedit::cursorDelegate()
textEditObject->setCursorPosition(0);
QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, textEditObject->positionToRectangle(5).center().toPoint());
QTest::qWait(50);
QTRY_VERIFY(textEditObject->cursorPosition() != 0);
QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
@@ -2666,7 +2701,7 @@ void tst_qquicktextedit::cursorDelegate()
}
//Test Delegate gets deleted
- textEditObject->setCursorDelegate(0);
+ textEditObject->setCursorDelegate(nullptr);
QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
}
@@ -2682,9 +2717,9 @@ void tst_qquicktextedit::remoteCursorDelegate()
view.setSource(testFileUrl("cursorTestRemote.qml"));
view.showNormal();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
// Delegate is created on demand, and so won't be available immediately. Focus in or
// setCursorVisible(true) will trigger creation.
@@ -2708,7 +2743,7 @@ void tst_qquicktextedit::cursorVisible()
QQuickView view(testFileUrl("cursorVisible.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(&view, qGuiApp->focusWindow());
QCOMPARE(edit.isCursorVisible(), false);
@@ -2740,13 +2775,13 @@ void tst_qquicktextedit::cursorVisible()
QWindow alternateView;
alternateView.show();
alternateView.requestActivate();
- QTest::qWaitForWindowActive(&alternateView);
+ QVERIFY(QTest::qWaitForWindowActive(&alternateView));
QCOMPARE(edit.isCursorVisible(), false);
QCOMPARE(spy.count(), 6);
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(edit.isCursorVisible(), true);
QCOMPARE(spy.count(), 7);
@@ -2829,7 +2864,7 @@ void tst_qquicktextedit::delegateLoading()
QTRY_VERIFY(view.rootObject());//Wait for loading to finish.
QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
// view.rootObject()->dumpObjectTree();
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
textEditObject->setFocus(true);
QQuickItem *delegate;
delegate = view.rootObject()->findChild<QQuickItem*>("delegateOkay");
@@ -2853,7 +2888,7 @@ void tst_qquicktextedit::cursorDelegateHeight()
QQuickView view(testFileUrl("cursorHeight.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
QVERIFY(textEditObject);
// Delegate creation is deferred until focus in or cursor visibility is forced.
@@ -2881,7 +2916,7 @@ void tst_qquicktextedit::cursorDelegateHeight()
QCOMPARE(delegateObject->height(), textEditObject->cursorRectangle().height());
// Test that the delegate gets deleted
- textEditObject->setCursorDelegate(0);
+ textEditObject->setCursorDelegate(nullptr);
QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
}
@@ -2895,11 +2930,11 @@ void tst_qquicktextedit::navigation()
window.show();
window.requestActivate();
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
- QVERIFY(input != 0);
+ QVERIFY(input != nullptr);
QTRY_VERIFY(input->hasActiveFocus());
simulateKey(&window, Qt::Key_Left);
QVERIFY(!input->hasActiveFocus());
@@ -2933,7 +2968,7 @@ void tst_qquicktextedit::copyAndPaste()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
// copy and paste
QCOMPARE(textEdit->text().length(), 12);
@@ -3009,7 +3044,7 @@ void tst_qquicktextedit::canPaste()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
// check initial value - QTBUG-17765
QTextDocument document;
@@ -3027,7 +3062,7 @@ void tst_qquicktextedit::canPasteEmpty()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
// check initial value - QTBUG-17765
QTextDocument document;
@@ -3046,11 +3081,11 @@ void tst_qquicktextedit::middleClickPaste()
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
- QVERIFY(textEditObject != 0);
+ QVERIFY(textEditObject != nullptr);
textEditObject->setFocus(true);
@@ -3082,11 +3117,11 @@ void tst_qquicktextedit::readOnly()
window.show();
window.requestActivate();
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
- QVERIFY(edit != 0);
+ QVERIFY(edit != nullptr);
QTRY_VERIFY(edit->hasActiveFocus());
QVERIFY(edit->isReadOnly());
QString initial = edit->text();
@@ -3117,7 +3152,7 @@ void tst_qquicktextedit::textInput()
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus());
@@ -3170,7 +3205,7 @@ void tst_qquicktextedit::inputMethodUpdate()
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus());
@@ -3204,7 +3239,7 @@ void tst_qquicktextedit::inputMethodUpdate()
// programmatical selections trigger update
platformInputContext.clear();
edit->selectAll();
- QCOMPARE(platformInputContext.m_updateCallCount, 1);
+ QVERIFY(platformInputContext.m_updateCallCount > 0);
// font changes
platformInputContext.clear();
@@ -3260,7 +3295,7 @@ void tst_qquicktextedit::openInputPanel()
QQuickView view(testFileUrl("openInputPanel.qml"));
view.showNormal();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
@@ -3274,7 +3309,7 @@ void tst_qquicktextedit::openInputPanel()
// input panel should open on focus
QPoint centerPoint(view.width()/2, view.height()/2);
- Qt::KeyboardModifiers noModifiers = 0;
+ Qt::KeyboardModifiers noModifiers = Qt::NoModifier;
QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QVERIFY(edit->hasActiveFocus());
@@ -3325,7 +3360,7 @@ void tst_qquicktextedit::openInputPanel()
QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
QCOMPARE(qApp->inputMethod()->isVisible(), false);
- inputMethodPrivate->testContext = 0;
+ inputMethodPrivate->testContext = nullptr;
}
void tst_qquicktextedit::geometrySignals()
@@ -3346,7 +3381,7 @@ void tst_qquicktextedit::pastingRichText_QTBUG_14003()
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickTextEdit *obj = qobject_cast<QQuickTextEdit*>(component.create());
- QTRY_VERIFY(obj != 0);
+ QTRY_VERIFY(obj != nullptr);
QTRY_COMPARE(obj->textFormat(), QQuickTextEdit::PlainText);
QMimeData *mData = new QMimeData;
@@ -3388,6 +3423,18 @@ void tst_qquicktextedit::implicitSize()
QCOMPARE(textObject->height(), textObject->implicitHeight());
}
+void tst_qquicktextedit::implicitSize_QTBUG_63153()
+{
+ QString componentStr = "import QtQuick 2.0\nTextEdit { }";
+ QQmlComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
+ textObject->setText("short");
+ qreal shortImplicitWidth = textObject->implicitWidth();
+ textObject->setText("in contrast to short this is long");
+ QVERIFY2(shortImplicitWidth < textObject->implicitWidth(), qPrintable(QString("%1 < %2").arg(textObject->implicitWidth()).arg(shortImplicitWidth)));
+}
+
void tst_qquicktextedit::contentSize()
{
QString componentStr = "import QtQuick 2.0\nTextEdit { width: 75; height: 16; font.pixelSize: 10 }";
@@ -3446,7 +3493,7 @@ void tst_qquicktextedit::implicitSizeBinding()
void tst_qquicktextedit::signal_editingfinished()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
window->setBaseSize(QSize(800,600));
window->setSource(testFileUrl("signal_editingfinished.qml"));
@@ -3455,7 +3502,7 @@ void tst_qquicktextedit::signal_editingfinished()
QVERIFY(QTest::qWaitForWindowActive(window));
QCOMPARE(QGuiApplication::focusWindow(), window);
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickTextEdit *input1 = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window->rootObject()->property("input1")));
QVERIFY(input1);
@@ -3646,7 +3693,7 @@ void tst_qquicktextedit::preeditCursorRectangle()
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
@@ -3729,7 +3776,7 @@ void tst_qquicktextedit::inputMethodComposing()
QQuickView view(testFileUrl("inputContext.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
@@ -3843,7 +3890,7 @@ void tst_qquicktextedit::cursorRectangleSize()
QFETCH(bool, useCursorDelegate);
QQuickView *window = new QQuickView(testFileUrl("positionAt.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window->rootObject());
QQmlComponent cursorDelegate(window->engine());
@@ -3856,11 +3903,11 @@ void tst_qquicktextedit::cursorRectangleSize()
textEdit->setX(10);
textEdit->setY(10);
textEdit->setCursorPosition(3);
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
textEdit->setFocus(true);
window->show();
window->requestActivate();
- QTest::qWaitForWindowActive(window);
+ QVERIFY(QTest::qWaitForWindowActive(window));
QInputMethodQueryEvent event(Qt::ImCursorRectangle);
qApp->sendEvent(textEdit, &event);
@@ -3994,7 +4041,7 @@ void tst_qquicktextedit::getText()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
QCOMPARE(textEdit->getText(start, end), expectedText);
}
@@ -4095,7 +4142,7 @@ void tst_qquicktextedit::getFormattedText()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
textEdit->setTextFormat(textFormat);
textEdit->setText(text);
@@ -4221,7 +4268,7 @@ void tst_qquicktextedit::append()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
textEdit->setTextFormat(textFormat);
textEdit->select(selectionStart, selectionEnd);
@@ -4436,7 +4483,7 @@ void tst_qquicktextedit::insert()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
textEdit->setTextFormat(textFormat);
textEdit->select(selectionStart, selectionEnd);
@@ -4678,7 +4725,7 @@ void tst_qquicktextedit::remove()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
textEdit->setTextFormat(textFormat);
textEdit->select(selectionStart, selectionEnd);
@@ -4859,13 +4906,13 @@ void tst_qquicktextedit::keySequence()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
QQuickWindow window;
textEdit->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
@@ -5021,13 +5068,13 @@ void tst_qquicktextedit::undo()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
QQuickWindow window;
textEdit->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
QVERIFY(!textEdit->canUndo());
@@ -5107,13 +5154,13 @@ void tst_qquicktextedit::redo()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
QQuickWindow window;
textEdit->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
QVERIFY(!textEdit->canUndo());
@@ -5328,13 +5375,13 @@ void tst_qquicktextedit::undo_keypressevents()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
QQuickWindow window;
textEdit->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
simulateKeys(&window, keys);
@@ -5352,13 +5399,13 @@ void tst_qquicktextedit::clear()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
QQuickWindow window;
textEdit->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textEdit->hasActiveFocus());
QSignalSpy spy(textEdit, SIGNAL(canUndoChanged()));
@@ -5462,7 +5509,7 @@ void tst_qquicktextedit::embeddedImages()
QQmlComponent textComponent(&engine, qmlfile);
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.beginCreate(engine.rootContext()));
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
const int baseUrlPropertyIndex = textObject->metaObject()->indexOfProperty("serverBaseUrl");
if (baseUrlPropertyIndex != -1) {
@@ -5490,11 +5537,11 @@ void tst_qquicktextedit::embeddedImages()
void tst_qquicktextedit::emptytags_QTBUG_22058()
{
QQuickView window(testFileUrl("qtbug-22058.qml"));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("inputField")));
QVERIFY(input->hasActiveFocus());
@@ -5513,7 +5560,7 @@ void tst_qquicktextedit::cursorRectangle_QTBUG_38947()
window.show();
window.requestActivate();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickTextEdit *edit = window.rootObject()->findChild<QQuickTextEdit *>("textedit");
QVERIFY(edit);
@@ -5551,7 +5598,7 @@ void tst_qquicktextedit::doubleSelect_QTBUG_38704()
QQmlComponent textEditComponent(&engine);
textEditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
- QVERIFY(textEdit != 0);
+ QVERIFY(textEdit != nullptr);
QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged()));
@@ -5575,7 +5622,7 @@ void tst_qquicktextedit::padding()
QQuickItem *root = window->rootObject();
QVERIFY(root);
QQuickTextEdit *obj = qobject_cast<QQuickTextEdit*>(root);
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
qreal cw = obj->contentWidth();
qreal ch = obj->contentHeight();
@@ -5654,6 +5701,36 @@ void tst_qquicktextedit::QTBUG_51115_readOnlyResetsSelection()
QCOMPARE(obj->selectedText(), QString());
}
+void tst_qquicktextedit::keys_shortcutoverride()
+{
+ // Tests that QML TextEdit receives Keys.onShortcutOverride (QTBUG-68711)
+ QQuickView view;
+ view.setSource(testFileUrl("keys_shortcutoverride.qml"));
+ view.show();
+ view.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+ QObject *root = view.rootObject();
+ QVERIFY(root);
+
+ QQuickTextEdit *textEdit = root->findChild<QQuickTextEdit*>();
+ QVERIFY(textEdit);
+ QQuickRectangle *rectangle = root->findChild<QQuickRectangle*>(QLatin1String("rectangle"));
+ QVERIFY(rectangle);
+
+ // Precondition: check if its not already changed
+ QCOMPARE(root->property("who").value<QString>(), QLatin1String("nobody"));
+
+ // send Key_Escape to the Rectangle
+ QVERIFY(rectangle->hasActiveFocus());
+ QTest::keyPress(&view, Qt::Key_Escape);
+ QCOMPARE(root->property("who").value<QString>(), QLatin1String("Rectangle"));
+
+ // send Key_Escape to TextEdit
+ textEdit->setFocus(true);
+ QTest::keyPress(&view, Qt::Key_Escape);
+ QCOMPARE(root->property("who").value<QString>(), QLatin1String("TextEdit"));
+}
+
QTEST_MAIN(tst_qquicktextedit)
#include "tst_qquicktextedit.moc"
diff --git a/tests/auto/quick/qquicktextinput/BLACKLIST b/tests/auto/quick/qquicktextinput/BLACKLIST
deleted file mode 100644
index e9f4f11c58..0000000000
--- a/tests/auto/quick/qquicktextinput/BLACKLIST
+++ /dev/null
@@ -1,3 +0,0 @@
-# QTBUG-41895
-[tripleClickSelectsAll]
-windows
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 67921e1fd0..ed2d535fda 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -215,6 +215,9 @@ private slots:
void clearInputMask();
void keypress_inputMask_data();
void keypress_inputMask();
+ void keypress_inputMethod_inputMask();
+ void keypress_inputMask_withValidator_data();
+ void keypress_inputMask_withValidator();
void hasAcceptableInputMask_data();
void hasAcceptableInputMask();
void maskCharacter_data();
@@ -297,7 +300,7 @@ void tst_qquicktextinput::cleanup()
{
// ensure not even skipped tests with custom input context leave it dangling
QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
- inputMethodPrivate->testContext = 0;
+ inputMethodPrivate->testContext = nullptr;
}
tst_qquicktextinput::tst_qquicktextinput()
@@ -329,7 +332,7 @@ void tst_qquicktextinput::text()
textinputComponent.setData("import QtQuick 2.0\nTextInput { text: \"\" }", QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->text(), QString(""));
QCOMPARE(textinputObject->length(), 0);
@@ -343,7 +346,7 @@ void tst_qquicktextinput::text()
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->text(), standard.at(i));
QCOMPARE(textinputObject->length(), standard.at(i).length());
@@ -360,7 +363,7 @@ void tst_qquicktextinput::width()
textinputComponent.setData("import QtQuick 2.0\nTextInput { text: \"\" }", QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->width(), 0.0);
delete textinputObject;
@@ -398,7 +401,7 @@ void tst_qquicktextinput::width()
qreal metricWidth = ceil(layout.boundingRect().width());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
int delta = abs(int(int(textinputObject->width()) - metricWidth));
QVERIFY(delta <= 3.0); // As best as we can hope for cross-platform.
@@ -415,7 +418,7 @@ void tst_qquicktextinput::font()
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->font().pointSize(), 40);
QCOMPARE(textinputObject->font().bold(), false);
QCOMPARE(textinputObject->font().italic(), false);
@@ -429,7 +432,7 @@ void tst_qquicktextinput::font()
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->font().bold(), true);
QCOMPARE(textinputObject->font().italic(), false);
@@ -442,7 +445,7 @@ void tst_qquicktextinput::font()
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->font().italic(), true);
QCOMPARE(textinputObject->font().bold(), false);
@@ -455,7 +458,7 @@ void tst_qquicktextinput::font()
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
QCOMPARE(textinputObject->font().bold(), false);
QCOMPARE(textinputObject->font().italic(), false);
@@ -469,7 +472,7 @@ void tst_qquicktextinput::font()
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->font().family(), QString(""));
delete textinputObject;
@@ -536,7 +539,7 @@ void tst_qquicktextinput::color()
QQmlComponent textinputComponent(&engine);
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
delete textinputObject;
@@ -549,7 +552,7 @@ void tst_qquicktextinput::color()
QQmlComponent textinputComponent(&engine);
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
delete textinputObject;
@@ -562,7 +565,7 @@ void tst_qquicktextinput::color()
QQmlComponent textinputComponent(&engine);
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
delete textinputObject;
@@ -578,7 +581,7 @@ void tst_qquicktextinput::color()
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QCOMPARE(textinputObject->color(), testColor);
delete textinputObject;
@@ -595,7 +598,7 @@ void tst_qquicktextinput::wrap()
QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
textHeight = textObject->height();
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->wrapMode(), QQuickTextInput::WrapAnywhere);
QCOMPARE(textObject->width(), 300.);
@@ -608,7 +611,7 @@ void tst_qquicktextinput::wrap()
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
- QVERIFY(textObject != 0);
+ QVERIFY(textObject != nullptr);
QCOMPARE(textObject->width(), 30.);
QVERIFY(textObject->height() > textHeight);
@@ -650,7 +653,7 @@ void tst_qquicktextinput::selection()
QQmlComponent textinputComponent(&engine);
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
//Test selection follows cursor
@@ -747,7 +750,7 @@ void tst_qquicktextinput::persistentSelection()
QQuickView window(testFileUrl("persistentSelection.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(window.rootObject());
QVERIFY(input);
@@ -790,7 +793,7 @@ void tst_qquicktextinput::overwriteMode()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QSignalSpy spy(textInput, SIGNAL(overwriteModeChanged(bool)));
@@ -798,7 +801,7 @@ void tst_qquicktextinput::overwriteMode()
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
@@ -1068,7 +1071,7 @@ void tst_qquicktextinput::moveCursorSelection()
QQmlComponent textinputComponent(&engine);
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
textinputObject->setCursorPosition(cursorPosition);
textinputObject->moveCursorSelection(movePosition, mode);
@@ -1276,7 +1279,7 @@ void tst_qquicktextinput::moveCursorSelectionSequence()
QQmlComponent textinputComponent(&engine);
textinputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
textinputObject->setCursorPosition(cursorPosition);
@@ -1301,19 +1304,19 @@ void tst_qquicktextinput::dragMouseSelection()
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
- QVERIFY(textInputObject != 0);
+ QVERIFY(textInputObject != nullptr);
// press-and-drag-and-release from x1 to x2
int x1 = 10;
int x2 = 70;
int y = textInputObject->height()/2;
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x1,y));
QTest::mouseMove(&window, QPoint(x2, y));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x2,y));
QString str1;
QTRY_VERIFY((str1 = textInputObject->selectedText()).length() > 3);
QTRY_VERIFY(str1.length() > 3);
@@ -1321,9 +1324,9 @@ void tst_qquicktextinput::dragMouseSelection()
// press and drag the current selection.
x1 = 40;
x2 = 100;
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x1,y));
QTest::mouseMove(&window, QPoint(x2, y));
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x2,y));
QString str2 = textInputObject->selectedText();
QTRY_VERIFY(str2.length() > 3);
@@ -1362,11 +1365,11 @@ void tst_qquicktextinput::mouseSelectionMode()
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
- QVERIFY(textInputObject != 0);
+ QVERIFY(textInputObject != nullptr);
textInputObject->setFocus(focus);
textInputObject->setFocusOnPress(focusOnPress);
@@ -1375,9 +1378,9 @@ void tst_qquicktextinput::mouseSelectionMode()
int x1 = 10;
int x2 = 70;
int y = textInputObject->height()/2;
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x1,y));
QTest::mouseMove(&window, QPoint(x2,y)); // doesn't work
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(x2,y));
if (selectWords) {
QTRY_COMPARE(textInputObject->selectedText(), text);
} else {
@@ -1468,7 +1471,7 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft()
QQuickView window(testFileUrl("horizontalAlignment_RightToLeft.qml"));
QQuickTextInput *textInput = window.rootObject()->findChild<QQuickTextInput*>("text");
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
window.show();
const QString rtlText = textInput->text();
@@ -1542,7 +1545,7 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft()
QCOMPARE(textInput->boundingRect().left(), qreal(0));
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
// If there is no committed text, the preedit text should determine the alignment.
@@ -1615,7 +1618,7 @@ void tst_qquicktextinput::verticalAlignment()
{
QQuickView window(testFileUrl("horizontalAlignment.qml"));
QQuickTextInput *textInput = window.rootObject()->findChild<QQuickTextInput*>("text");
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
window.showNormal();
QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignTop);
@@ -1802,13 +1805,13 @@ void tst_qquicktextinput::boundingRect()
void tst_qquicktextinput::positionAt()
{
QQuickView window(testFileUrl("positionAt.qml"));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
// Check autoscrolled...
@@ -1892,13 +1895,13 @@ void tst_qquicktextinput::positionAt()
void tst_qquicktextinput::maxLength()
{
QQuickView window(testFileUrl("maxLength.qml"));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QVERIFY(textinputObject->text().isEmpty());
QCOMPARE(textinputObject->maxLength(), 10);
foreach (const QString &str, standard) {
@@ -1924,9 +1927,9 @@ void tst_qquicktextinput::masks()
QQuickView window(testFileUrl("masks.qml"));
window.show();
window.requestActivate();
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
- QVERIFY(textinputObject != 0);
+ QVERIFY(textinputObject != nullptr);
QTRY_VERIFY(textinputObject->hasActiveFocus());
QCOMPARE(textinputObject->text().length(), 0);
QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
@@ -1954,9 +1957,9 @@ void tst_qquicktextinput::validators()
QQuickView window(testFileUrl("validators.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QLocale defaultLocale;
QLocale enLocale("en");
@@ -1987,9 +1990,6 @@ void tst_qquicktextinput::validators()
QCOMPARE(intInput->hasAcceptableInput(), false);
QCOMPARE(intInput->property("acceptable").toBool(), false);
QCOMPARE(intSpy.count(), 0);
- QTest::keyPress(&window, Qt::Key_2);
- QTest::keyRelease(&window, Qt::Key_2, Qt::NoModifier);
- QTRY_COMPARE(intInput->text(), QLatin1String("1"));
QCOMPARE(intInput->hasAcceptableInput(), false);
QCOMPARE(intInput->property("acceptable").toBool(), false);
QCOMPARE(intSpy.count(), 0);
@@ -2244,12 +2244,12 @@ void tst_qquicktextinput::inputMethods()
QQuickView window(testFileUrl("inputmethods.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
// test input method hints
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(window.rootObject());
- QVERIFY(input != 0);
+ QVERIFY(input != nullptr);
QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText);
QSignalSpy inputMethodHintSpy(input, SIGNAL(inputMethodHintsChanged()));
input->setInputMethodHints(Qt::ImhUppercaseOnly);
@@ -2291,8 +2291,9 @@ void tst_qquicktextinput::inputMethods()
QGuiApplication::sendEvent(input, &event);
QCOMPARE(input->text(), QString("Our Goodbye world!"));
QCOMPARE(input->displayText(), QString("Our Goodbye world!"));
- QCOMPARE(input->cursorPosition(), 7);
+ QCOMPARE(input->cursorPosition(), 3);
+ input->setCursorPosition(7);
QInputMethodEvent preeditEvent("PREEDIT", QList<QInputMethodEvent::Attribute>());
QGuiApplication::sendEvent(input, &preeditEvent);
QCOMPARE(input->text(), QString("Our Goodbye world!"));
@@ -2335,9 +2336,9 @@ void tst_qquicktextinput::signal_accepted()
QQuickView window(testFileUrl("signal_accepted.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("input")));
QVERIFY(input);
@@ -2377,9 +2378,9 @@ void tst_qquicktextinput::signal_editingfinished()
QQuickView window(testFileUrl("signal_editingfinished.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input1 = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("input1")));
QVERIFY(input1);
@@ -2447,7 +2448,7 @@ void tst_qquicktextinput::signal_textEdited()
QQuickWindow window;
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextInput *input = new QQuickTextInput(window.contentItem());
QVERIFY(input);
@@ -2504,11 +2505,11 @@ void tst_qquicktextinput::navigation()
window.show();
window.requestActivate();
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
- QVERIFY(input != 0);
+ QVERIFY(input != nullptr);
input->setCursorPosition(0);
QTRY_VERIFY(input->hasActiveFocus());
simulateKey(&window, Qt::Key_Left);
@@ -2553,11 +2554,11 @@ void tst_qquicktextinput::navigation_RTL()
window.show();
window.requestActivate();
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
- QVERIFY(input != 0);
+ QVERIFY(input != nullptr);
const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
input->setText(QString::fromUtf16(arabic_str, 11));
@@ -2594,7 +2595,7 @@ void tst_qquicktextinput::copyAndPaste()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
// copy and paste
QCOMPARE(textInput->text().length(), 12);
@@ -2673,7 +2674,7 @@ void tst_qquicktextinput::copyAndPaste()
QCOMPARE(clipboard->text(), QString("My password"));
clipboard->clear();
} else {
- QVERIFY(clipboard->text().isEmpty());
+ QVERIFY(!clipboard->ownsSelection() || clipboard->text().isEmpty());
}
index++;
}
@@ -2692,13 +2693,13 @@ void tst_qquicktextinput::copyAndPasteKeySequence()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QQuickWindow window;
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
// copy and paste
QVERIFY(textInput->hasActiveFocus());
@@ -2741,7 +2742,7 @@ void tst_qquicktextinput::copyAndPasteKeySequence()
QCOMPARE(clipboard->text(), QString("My password"));
clipboard->clear();
} else {
- QVERIFY(clipboard->text().isEmpty());
+ QVERIFY(!clipboard->ownsClipboard() || clipboard->text().isEmpty());
}
index++;
}
@@ -2759,7 +2760,7 @@ void tst_qquicktextinput::canPasteEmpty()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
QCOMPARE(textInput->canPaste(), cp);
@@ -2775,7 +2776,7 @@ void tst_qquicktextinput::canPaste()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
QCOMPARE(textInput->canPaste(), cp);
@@ -2792,11 +2793,11 @@ void tst_qquicktextinput::middleClickPaste()
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
- QVERIFY(textInputObject != 0);
+ QVERIFY(textInputObject != nullptr);
textInputObject->setFocus(true);
@@ -2831,7 +2832,7 @@ void tst_qquicktextinput::passwordCharacter()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
textInput->setPasswordCharacter("X");
qreal implicitWidth = textInput->implicitWidth();
@@ -2857,9 +2858,9 @@ void tst_qquicktextinput::cursorDelegate()
QQuickView view(source);
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextInput *textInputObject = view.rootObject()->findChild<QQuickTextInput*>("textInputObject");
- QVERIFY(textInputObject != 0);
+ QVERIFY(textInputObject != nullptr);
// Delegate is created on demand, and so won't be available immediately. Focus in or
// setCursorVisible(true) will trigger creation.
QTRY_VERIFY(!textInputObject->findChild<QQuickItem*>("cursorInstance"));
@@ -2885,7 +2886,7 @@ void tst_qquicktextinput::cursorDelegate()
textInputObject->setCursorPosition(0);
const QPoint point1 = textInputObject->positionToRectangle(5).center().toPoint();
QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, 0, point1);
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, point1);
QTest::qWait(50);
QTRY_VERIFY(textInputObject->cursorPosition() != 0);
QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
@@ -2895,10 +2896,10 @@ void tst_qquicktextinput::cursorDelegate()
textInputObject->setCursorPosition(0);
const QPoint point2 = textInputObject->positionToRectangle(10).center().toPoint();
QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mousePress(&view, Qt::LeftButton, 0, point1);
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, point1);
QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
QGuiApplication::sendEvent(&view, &mv);
- QTest::mouseRelease(&view, Qt::LeftButton, 0, point2);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, point2);
QTest::qWait(50);
QTRY_COMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
@@ -2906,7 +2907,7 @@ void tst_qquicktextinput::cursorDelegate()
textInputObject->setReadOnly(true);
textInputObject->setCursorPosition(0);
QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, 0, textInputObject->positionToRectangle(5).center().toPoint());
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, textInputObject->positionToRectangle(5).center().toPoint());
QTest::qWait(50);
QTRY_VERIFY(textInputObject->cursorPosition() != 0);
QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
@@ -2914,7 +2915,7 @@ void tst_qquicktextinput::cursorDelegate()
textInputObject->setCursorPosition(0);
QTest::qWait(400); //ensure this isn't treated as a double-click
- QTest::mouseClick(&view, Qt::LeftButton, 0, textInputObject->positionToRectangle(5).center().toPoint());
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, textInputObject->positionToRectangle(5).center().toPoint());
QTest::qWait(50);
QTRY_VERIFY(textInputObject->cursorPosition() != 0);
QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
@@ -2960,7 +2961,7 @@ void tst_qquicktextinput::cursorDelegate()
}
//Test Delegate gets deleted
- textInputObject->setCursorDelegate(0);
+ textInputObject->setCursorDelegate(nullptr);
QVERIFY(!textInputObject->findChild<QQuickItem*>("cursorInstance"));
}
@@ -2975,9 +2976,9 @@ void tst_qquicktextinput::remoteCursorDelegate()
view.setSource(testFileUrl("cursorTestRemote.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextInput *textInputObject = view.rootObject()->findChild<QQuickTextInput*>("textInputObject");
- QVERIFY(textInputObject != 0);
+ QVERIFY(textInputObject != nullptr);
// Delegate is created on demand, and so won't be available immediately. Focus in or
// setCursorVisible(true) will trigger creation.
@@ -3002,7 +3003,7 @@ void tst_qquicktextinput::cursorVisible()
QQuickView view(testFileUrl("cursorVisible.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(input.isCursorVisible(), false);
@@ -3033,13 +3034,13 @@ void tst_qquicktextinput::cursorVisible()
QQuickView alternateView;
alternateView.show();
alternateView.requestActivate();
- QTest::qWaitForWindowActive(&alternateView);
+ QVERIFY(QTest::qWaitForWindowActive(&alternateView));
QCOMPARE(input.isCursorVisible(), false);
QCOMPARE(spy.count(), 6);
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(input.isCursorVisible(), true);
QCOMPARE(spy.count(), 7);
@@ -3303,11 +3304,11 @@ void tst_qquicktextinput::readOnly()
window.show();
window.requestActivate();
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
- QVERIFY(input != 0);
+ QVERIFY(input != nullptr);
QTRY_VERIFY(input->hasActiveFocus());
QVERIFY(input->isReadOnly());
QVERIFY(!input->isCursorVisible());
@@ -3331,13 +3332,13 @@ void tst_qquicktextinput::echoMode()
QQuickView window(testFileUrl("echoMode.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
- QVERIFY(input != 0);
+ QVERIFY(input != nullptr);
QTRY_VERIFY(input->hasActiveFocus());
QString initial = input->text();
Qt::InputMethodHints ref;
@@ -3407,9 +3408,9 @@ void tst_qquicktextinput::passwordEchoDelay()
QQuickView window(testFileUrl("echoMode.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
QVERIFY(input);
@@ -3474,8 +3475,8 @@ void tst_qquicktextinput::passwordEchoDelay()
void tst_qquicktextinput::simulateKey(QWindow *view, int key)
{
- QKeyEvent press(QKeyEvent::KeyPress, key, 0);
- QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
+ QKeyEvent press(QKeyEvent::KeyPress, key, nullptr);
+ QKeyEvent release(QKeyEvent::KeyRelease, key, nullptr);
QGuiApplication::sendEvent(view, &press);
QGuiApplication::sendEvent(view, &release);
@@ -3496,7 +3497,7 @@ void tst_qquicktextinput::focusOnPress()
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput*>(texteditComponent.create());
- QVERIFY(textInputObject != 0);
+ QVERIFY(textInputObject != nullptr);
QCOMPARE(textInputObject->focusOnPress(), true);
QCOMPARE(textInputObject->hasFocus(), false);
@@ -3513,12 +3514,12 @@ void tst_qquicktextinput::focusOnPress()
textInputObject->setParentItem(window.contentItem());
window.showNormal();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(textInputObject->hasFocus(), false);
QCOMPARE(textInputObject->hasActiveFocus(), false);
- Qt::KeyboardModifiers noModifiers = 0;
+ Qt::KeyboardModifiers noModifiers = Qt::NoModifier;
QTest::mousePress(&window, Qt::LeftButton, noModifiers);
QGuiApplication::processEvents();
QCOMPARE(textInputObject->hasFocus(), true);
@@ -3571,7 +3572,7 @@ void tst_qquicktextinput::focusOnPressOnlyOneItem()
QQuickView window(testFileUrl("focusOnlyOneOnPress.qml"));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextInput *first = window.rootObject()->findChild<QQuickTextInput*>("first");
QQuickTextInput *second = window.rootObject()->findChild<QQuickTextInput*>("second");
@@ -3592,7 +3593,7 @@ void tst_qquicktextinput::focusOnPressOnlyOneItem()
//
// this is a contrived example to be sure, but at the end of this, the
// important thing is that only one thing should have activeFocus.
- Qt::KeyboardModifiers noModifiers = 0;
+ Qt::KeyboardModifiers noModifiers = nullptr;
QTest::mousePress(&window, Qt::LeftButton, noModifiers, QPoint(10, 10));
// make sure the press is processed.
@@ -3615,7 +3616,7 @@ void tst_qquicktextinput::openInputPanel()
QQuickView view(testFileUrl("openInputPanel.qml"));
view.showNormal();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
QVERIFY(input);
@@ -3627,7 +3628,7 @@ void tst_qquicktextinput::openInputPanel()
QCOMPARE(qApp->inputMethod()->isVisible(), false);
// input panel should open on focus
- Qt::KeyboardModifiers noModifiers = 0;
+ Qt::KeyboardModifiers noModifiers = nullptr;
QTest::mousePress(&view, Qt::LeftButton, noModifiers);
QGuiApplication::processEvents();
QVERIFY(input->hasActiveFocus());
@@ -3683,7 +3684,7 @@ void tst_qquicktextinput::openInputPanel()
class MyTextInput : public QQuickTextInput
{
public:
- MyTextInput(QQuickItem *parent = 0) : QQuickTextInput(parent)
+ MyTextInput(QQuickItem *parent = nullptr) : QQuickTextInput(parent)
{
nbPaint = 0;
}
@@ -3704,7 +3705,7 @@ void tst_qquicktextinput::setHAlignClearCache()
input.setParentItem(view.contentItem());
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_COMPARE(input.nbPaint, 1);
input.setHAlign(QQuickTextInput::AlignRight);
//Changing the alignment should trigger a repaint
@@ -3724,7 +3725,7 @@ void tst_qquicktextinput::focusOutClearSelection()
input2.componentComplete();
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QVERIFY(input.hasActiveFocus());
input.select(2,5);
//The selection should work
@@ -3745,7 +3746,7 @@ void tst_qquicktextinput::focusOutNotClearSelection()
input.componentComplete();
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QVERIFY(input.hasActiveFocus());
input.select(2,5);
@@ -3838,7 +3839,7 @@ void tst_qquicktextinput::preeditAutoScroll()
QQuickView view(testFileUrl("preeditAutoScroll.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
QVERIFY(input);
QVERIFY(input->hasActiveFocus());
@@ -3924,7 +3925,7 @@ void tst_qquicktextinput::preeditCursorRectangle()
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
QVERIFY(input);
QVERIFY(input->hasActiveFocus());
@@ -4007,7 +4008,7 @@ void tst_qquicktextinput::inputContextMouseHandler()
view.showNormal();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QTextLayout layout(text);
layout.setFont(input->font());
@@ -4043,7 +4044,7 @@ void tst_qquicktextinput::inputMethodComposing()
QQuickView view(testFileUrl("inputContext.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
QVERIFY(input);
QVERIFY(input->hasActiveFocus());
@@ -4149,7 +4150,7 @@ void tst_qquicktextinput::inputMethodUpdate()
QQuickView view(testFileUrl("inputContext.qml"));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
QVERIFY(input);
QVERIFY(input->hasActiveFocus());
@@ -4228,18 +4229,18 @@ void tst_qquicktextinput::inputMethodUpdate()
void tst_qquicktextinput::cursorRectangleSize()
{
QQuickView *window = new QQuickView(testFileUrl("positionAt.qml"));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickTextInput *textInput = qobject_cast<QQuickTextInput *>(window->rootObject());
// make sure cursor rectangle is not at (0,0)
textInput->setX(10);
textInput->setY(10);
textInput->setCursorPosition(3);
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
textInput->setFocus(true);
window->show();
window->requestActivate();
- QTest::qWaitForWindowActive(window);
+ QVERIFY(QTest::qWaitForWindowActive(window));
QVERIFY(textInput->hasActiveFocus());
QInputMethodQueryEvent event(Qt::ImCursorRectangle);
@@ -4271,7 +4272,7 @@ void tst_qquicktextinput::tripleClickSelectsAll()
QQuickView view(QUrl::fromLocalFile(qmlfile));
view.show();
view.requestActivate();
- QTest::qWaitForWindowActive(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QQuickTextInput* input = qobject_cast<QQuickTextInput*>(view.rootObject());
QVERIFY(input);
@@ -4283,24 +4284,24 @@ void tst_qquicktextinput::tripleClickSelectsAll()
// Clicking on the same point inside TextInput three times in a row
// should trigger a triple click, thus selecting all the text.
QPoint pointInside = input->position().toPoint() + QPoint(2,2);
- QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
- QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
+ QTest::mouseDClick(&view, Qt::LeftButton, Qt::NoModifier, pointInside);
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, pointInside);
QGuiApplication::processEvents();
QCOMPARE(input->selectedText(), hello);
// Now it simulates user moving the mouse between the second and the third click.
// In this situation, we don't expect a triple click.
QPoint pointInsideButFar = QPoint(input->width(),input->height()) - QPoint(2,2);
- QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
- QTest::mouseClick(&view, Qt::LeftButton, 0, pointInsideButFar);
+ QTest::mouseDClick(&view, Qt::LeftButton, Qt::NoModifier, pointInside);
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, pointInsideButFar);
QGuiApplication::processEvents();
QVERIFY(input->selectedText().isEmpty());
// And now we press the third click too late, so no triple click event is triggered.
- QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
+ QTest::mouseDClick(&view, Qt::LeftButton, Qt::NoModifier, pointInside);
QGuiApplication::processEvents();
QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 1);
- QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
+ QTest::mouseClick(&view, Qt::LeftButton, Qt::NoModifier, pointInside);
QGuiApplication::processEvents();
QVERIFY(input->selectedText().isEmpty());
}
@@ -4370,7 +4371,7 @@ void tst_qquicktextinput::getText()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QCOMPARE(textInput->getText(start, end), expectedText);
}
@@ -4710,7 +4711,7 @@ void tst_qquicktextinput::insert()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
textInput->select(selectionStart, selectionEnd);
@@ -5065,7 +5066,7 @@ void tst_qquicktextinput::remove()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
textInput->select(selectionStart, selectionEnd);
@@ -5260,14 +5261,14 @@ void tst_qquicktextinput::keySequence()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
textInput->setEchoMode(echoMode);
QQuickWindow window;
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
simulateKey(&window, layoutDirection);
@@ -5422,13 +5423,13 @@ void tst_qquicktextinput::undo()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QQuickWindow window;
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
QVERIFY(!textInput->canUndo());
@@ -5508,13 +5509,13 @@ void tst_qquicktextinput::redo()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QQuickWindow window;
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
QVERIFY(!textInput->canUndo());
@@ -5840,13 +5841,13 @@ void tst_qquicktextinput::undo_keypressevents()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QQuickWindow window;
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
simulateKeys(&window, keys);
@@ -5864,13 +5865,13 @@ void tst_qquicktextinput::clear()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QQuickWindow window;
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
QVERIFY(!textInput->canUndo());
@@ -5918,7 +5919,7 @@ void tst_qquicktextinput::backspaceSurrogatePairs()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
textInput->setText(text);
textInput->setCursorPosition(text.length());
@@ -5952,8 +5953,8 @@ void tst_qquicktextinput::QTBUG_19956()
QQuickView window(testFileUrl(url));
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput*>(window.rootObject());
QVERIFY(input);
input->setFocus(true);
@@ -5985,14 +5986,14 @@ void tst_qquicktextinput::QTBUG_19956_regexp()
{
QUrl url = testFileUrl("qtbug-19956regexp.qml");
- QString warning = url.toString() + ":11:17: Unable to assign [undefined] to QRegExp";
+ QString warning = url.toString() + ":11:9: Unable to assign [undefined] to QRegExp";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QQuickView window(url);
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
- QVERIFY(window.rootObject() != 0);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QVERIFY(window.rootObject() != nullptr);
QQuickTextInput *input = qobject_cast<QQuickTextInput*>(window.rootObject());
QVERIFY(input);
input->setFocus(true);
@@ -6110,6 +6111,87 @@ void tst_qquicktextinput::negativeDimensions()
QCOMPARE(input->height(), qreal(-1));
}
+void tst_qquicktextinput::keypress_inputMask_withValidator_data()
+{
+ QTest::addColumn<QString>("mask");
+ QTest::addColumn<qreal>("validatorMinimum");
+ QTest::addColumn<qreal>("validatorMaximum");
+ QTest::addColumn<int>("decimals");
+ QTest::addColumn<QString>("validatorRegExp");
+ QTest::addColumn<KeyList>("keys");
+ QTest::addColumn<QString>("expectedText");
+ QTest::addColumn<QString>("expectedDisplayText");
+
+ {
+ KeyList keys;
+ // inserting '1212' then two backspaces
+ keys << Qt::Key_Home << "1212" << Qt::Key_Backspace << Qt::Key_Backspace;
+ QTest::newRow("backspaceWithInt") << QString("9999;_") << 1.0 << 9999.00 << 0 << QString()
+ << keys << QString("12") << QString("12__");
+ }
+ {
+ KeyList keys;
+ // inserting '12.12' then two backspaces
+ keys << Qt::Key_Home << "12.12" << Qt::Key_Backspace << Qt::Key_Backspace;
+ QTest::newRow("backspaceWithDouble") << QString("99.99;_") << 1.0 << 99.99 << 2 << QString()
+ << keys << QString("12.") << QString("12.__");
+ }
+ {
+ KeyList keys;
+ // inserting '1111.11' then two backspaces
+ keys << Qt::Key_Home << "1111.11" << Qt::Key_Backspace << Qt::Key_Backspace;
+ QTest::newRow("backspaceWithRegExp") << QString("9999;_") << 0.0 << 0.0 << 0
+ << QString("/^[-]?((\\.\\d+)|(\\d+(\\.\\d+)?))$/")
+ << keys << QString("11") << QString("11__");
+ }
+ {
+ KeyList keys;
+ // inserting '99' - QTBUG-64616
+ keys << Qt::Key_Home << "99";
+ QTest::newRow("invalidTextWithRegExp") << QString("X9;_") << 0.0 << 0.0 << 0
+ << QString("/[+-][0+9]/")
+ << keys << QString("") << QString("__");
+ }
+}
+
+void tst_qquicktextinput::keypress_inputMask_withValidator()
+{
+ QFETCH(QString, mask);
+ QFETCH(qreal, validatorMinimum);
+ QFETCH(qreal, validatorMaximum);
+ QFETCH(int, decimals);
+ QFETCH(QString, validatorRegExp);
+ QFETCH(KeyList, keys);
+ QFETCH(QString, expectedText);
+ QFETCH(QString, expectedDisplayText);
+
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\"\n";
+ if (!validatorRegExp.isEmpty())
+ componentStr += "validator: RegExpValidator { regExp: " + validatorRegExp + " }\n}";
+ else if (decimals > 0)
+ componentStr += QString("validator: DoubleValidator { bottom: %1; decimals: %2; top: %3 }\n}").
+ arg(validatorMinimum).arg(decimals).arg(validatorMaximum);
+ else
+ componentStr += QString("validator: IntValidator { bottom: %1; top: %2 }\n}").
+ arg((int)validatorMinimum).arg((int)validatorMaximum);
+
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != nullptr);
+
+ QQuickWindow window;
+ textInput->setParentItem(window.contentItem());
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QVERIFY(textInput->hasActiveFocus());
+
+ simulateKeys(&window, keys);
+
+ QCOMPARE(textInput->text(), expectedText);
+ QCOMPARE(textInput->displayText(), expectedDisplayText);
+}
void tst_qquicktextinput::setInputMask_data()
{
@@ -6326,7 +6408,7 @@ void tst_qquicktextinput::setInputMask()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
// then either insert using insert() or keyboard
if (insert_text) {
@@ -6336,7 +6418,7 @@ void tst_qquicktextinput::setInputMask()
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
simulateKey(&window, Qt::Key_Home);
@@ -6383,7 +6465,7 @@ void tst_qquicktextinput::inputMask()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QCOMPARE(textInput->inputMask(), expectedMask);
}
@@ -6394,7 +6476,7 @@ void tst_qquicktextinput::clearInputMask()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QVERIFY(!textInput->inputMask().isEmpty());
textInput->setInputMask(QString());
@@ -6466,13 +6548,13 @@ void tst_qquicktextinput::keypress_inputMask()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
QQuickWindow window;
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QVERIFY(textInput->hasActiveFocus());
simulateKeys(&window, keys);
@@ -6481,6 +6563,48 @@ void tst_qquicktextinput::keypress_inputMask()
QCOMPARE(textInput->displayText(), expectedDisplayText);
}
+void tst_qquicktextinput::keypress_inputMethod_inputMask()
+{
+ // Similar to the keypress_inputMask test, but this is done solely via
+ // input methods
+ QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"AA.AA.AA\" }";
+ QQmlComponent textInputComponent(&engine);
+ textInputComponent.setData(componentStr.toLatin1(), QUrl());
+ QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
+ QVERIFY(textInput != nullptr);
+
+ QQuickWindow window;
+ textInput->setParentItem(window.contentItem());
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ QVERIFY(textInput->hasActiveFocus());
+
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString("EE");
+ QGuiApplication::sendEvent(textInput, &event);
+ }
+ QCOMPARE(textInput->cursorPosition(), 3);
+ QCOMPARE(textInput->text(), QStringLiteral("EE.."));
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString("EE");
+ QGuiApplication::sendEvent(textInput, &event);
+ }
+ QCOMPARE(textInput->cursorPosition(), 6);
+ QCOMPARE(textInput->text(), QStringLiteral("EE.EE."));
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString("EE");
+ QGuiApplication::sendEvent(textInput, &event);
+ }
+ QCOMPARE(textInput->cursorPosition(), 8);
+ QCOMPARE(textInput->text(), QStringLiteral("EE.EE.EE"));
+}
void tst_qquicktextinput::hasAcceptableInputMask_data()
{
@@ -6512,7 +6636,7 @@ void tst_qquicktextinput::hasAcceptableInputMask()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
// test that invalid input (for required) work for optionalMask
textInput->setText(invalid);
@@ -6566,7 +6690,7 @@ void tst_qquicktextinput::maskCharacter()
QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
- QVERIFY(textInput != 0);
+ QVERIFY(textInput != nullptr);
for (int i = 0; i < input.size(); ++i) {
QString in = QString(input.at(i));
@@ -6579,7 +6703,7 @@ void tst_qquicktextinput::maskCharacter()
class TestValidator : public QValidator
{
public:
- TestValidator(QObject *parent = 0) : QValidator(parent) { }
+ TestValidator(QObject *parent = nullptr) : QValidator(parent) { }
State validate(QString &input, int &) const { return input == QStringLiteral("ok") ? Acceptable : Intermediate; }
void fixup(QString &input) const { input = QStringLiteral("ok"); }
@@ -6590,7 +6714,7 @@ void tst_qquicktextinput::fixup()
QQuickWindow window;
window.show();
window.requestActivate();
- QTest::qWaitForWindowActive(&window);
+ QVERIFY(QTest::qWaitForWindowActive(&window));
QQuickTextInput *input = new QQuickTextInput(window.contentItem());
input->setValidator(new TestValidator(input));
@@ -6799,7 +6923,7 @@ void tst_qquicktextinput::padding()
QQuickItem *root = window->rootObject();
QVERIFY(root);
QQuickTextInput *obj = qobject_cast<QQuickTextInput*>(root);
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
qreal cw = obj->contentWidth();
qreal ch = obj->contentHeight();
diff --git a/tests/auto/quick/qquickview/qquickview.pro b/tests/auto/quick/qquickview/qquickview.pro
index 1302908bf7..12b24a4e27 100644
--- a/tests/auto/quick/qquickview/qquickview.pro
+++ b/tests/auto/quick/qquickview/qquickview.pro
@@ -5,6 +5,7 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qquickview.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
TESTDATA = data/*
diff --git a/tests/auto/quick/qquickview/tst_qquickview.cpp b/tests/auto/quick/qquickview/tst_qquickview.cpp
index 04d21457e6..e259ed1ae7 100644
--- a/tests/auto/quick/qquickview/tst_qquickview.cpp
+++ b/tests/auto/quick/qquickview/tst_qquickview.cpp
@@ -36,29 +36,7 @@
#include <QtCore/QDebug>
#include <QtQml/qqmlengine.h>
-class SizeChangesListener : public QObject, public QVector<QSize>
-{
- Q_OBJECT
-public:
- explicit SizeChangesListener(QQuickItem *item);
-private slots:
- void onSizeChanged();
-private:
- QQuickItem *item;
-
-};
-
-SizeChangesListener::SizeChangesListener(QQuickItem *item) :
- item(item)
-{
- connect(item, &QQuickItem::widthChanged, this, &SizeChangesListener::onSizeChanged);
- connect(item, &QQuickItem::heightChanged, this, &SizeChangesListener::onSizeChanged);
-}
-
-void SizeChangesListener::onSizeChanged()
-{
- append(QSize(item->width(), item->height()));
-}
+#include "../shared/geometrytestutil.h"
class tst_QQuickView : public QQmlDataTest
{
@@ -164,7 +142,7 @@ void tst_QQuickView::resizemodeitem()
// size update from view
QCoreApplication::processEvents(); // make sure the last resize events are gone
- SizeChangesListener sizeListener(item);
+ QSizeChangeListener sizeListener(item);
view->resize(QSize(200,300));
QTRY_COMPARE(item->width(), 200.0);
@@ -234,11 +212,11 @@ void tst_QQuickView::engine()
QQmlEngine *engine = new QQmlEngine;
QVERIFY(!engine->incubationController());
- QQuickView *view = new QQuickView(engine, 0);
+ QQuickView *view = new QQuickView(engine, nullptr);
QVERIFY(view);
QCOMPARE(engine->incubationController(), view->incubationController());
- QQuickView *view2 = new QQuickView(engine, 0);
+ QQuickView *view2 = new QQuickView(engine, nullptr);
QVERIFY(view);
QCOMPARE(engine->incubationController(), view->incubationController());
delete view;
@@ -250,7 +228,7 @@ void tst_QQuickView::engine()
QVERIFY(!engine->incubationController());
QQuickView *view3 = new QQuickView;
- QQuickView *view4 = new QQuickView(view3->engine(), 0);
+ QQuickView *view4 = new QQuickView(view3->engine(), nullptr);
QVERIFY(view3->engine());
QVERIFY(view4->engine());
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/create.qml b/tests/auto/quick/qquickvisualdatamodel/data/create.qml
index 9f4b754552..ba63bc778d 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/create.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/create.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
ListView {
width: 200
@@ -6,7 +7,7 @@ ListView {
property var persistentHandle
- model: VisualDataModel {
+ model: DelegateModel {
id: visualModel
persistedItems.includeByDefault: true
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/datalist-package.qml b/tests/auto/quick/qquickvisualdatamodel/data/datalist-package.qml
index ae3bd81d91..3fc33755d3 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/datalist-package.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/datalist-package.qml
@@ -1,10 +1,11 @@
import QtQuick 2.0
+import QtQml.Models 2.12
ListView {
width: 100
height: 100
model: visualModel.parts.package
- VisualDataModel {
+ DelegateModel {
id: visualModel
objectName: "visualModel"
model: myModel
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/datalist.qml b/tests/auto/quick/qquickvisualdatamodel/data/datalist.qml
index 8ce59caddc..074f5ad26f 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/datalist.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/datalist.qml
@@ -1,9 +1,10 @@
import QtQuick 2.0
+import QtQml.Models 2.12
ListView {
width: 100
height: 100
- model: VisualDataModel {
+ model: DelegateModel {
id: visualModel
objectName: "visualModel"
model: myModel
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml b/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml
new file mode 100644
index 0000000000..44c157b824
--- /dev/null
+++ b/tests/auto/quick/qquickvisualdatamodel/data/externalManagedModel.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tests of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick.Window 2.2
+import QtQuick 2.6
+import QtQml.Models 2.11
+import example 1.0
+
+Window {
+ visible: true
+ property bool running: rebuildTimer.running
+ ListView {
+ anchors.fill: parent
+ model: delegateModel
+ }
+
+ DelegateModel {
+ id: delegateModel
+ model: objectsProvider.objects
+ delegate: Item {}
+ }
+
+ Timer {
+ id: rebuildTimer
+ running: true
+ repeat: true
+ interval: 1
+
+ property int count: 0
+ onTriggered: {
+ objectsProvider.rebuild();
+ if (++count === 10)
+ running = false;
+ }
+ }
+
+ ObjectsProvider {
+ id: objectsProvider
+ }
+}
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/groups-invalid.qml b/tests/auto/quick/qquickvisualdatamodel/data/groups-invalid.qml
index 70c6f9f995..c40abc1112 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/groups-invalid.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/groups-invalid.qml
@@ -1,14 +1,15 @@
import QtQuick 2.0
+import QtQml.Models 2.12
-VisualDataModel {
+DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" },
- VisualDataGroup { id: unnamed; objectName: "unnamed" },
- VisualDataGroup { id: capitalised; objectName: "capitalised"; name: "Capitalised" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" },
+ DelegateModelGroup { id: unnamed; objectName: "unnamed" },
+ DelegateModelGroup { id: capitalised; objectName: "capitalised"; name: "Capitalised" }
]
}
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/groups-package.qml b/tests/auto/quick/qquickvisualdatamodel/data/groups-package.qml
index ea5ad5d3bd..ada472e376 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/groups-package.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/groups-package.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
ListView {
width: 100
@@ -12,14 +13,14 @@ ListView {
}
model: visualModel.parts.package
- VisualDataModel {
+ DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: myModel
@@ -28,16 +29,16 @@ ListView {
property variant test1: name
property variant test2: index
- property variant test3: VisualDataModel.itemsIndex
- property variant test4: VisualDataModel.inItems
- property variant test5: VisualDataModel.visibleIndex
- property variant test6: VisualDataModel.inVisible
- property variant test7: VisualDataModel.selectedIndex
- property variant test8: VisualDataModel.inSelected
- property variant test9: VisualDataModel.groups
-
- function hide() { VisualDataModel.inVisible = false }
- function select() { VisualDataModel.inSelected = true }
+ property variant test3: DelegateModel.itemsIndex
+ property variant test4: DelegateModel.inItems
+ property variant test5: DelegateModel.visibleIndex
+ property variant test6: DelegateModel.inVisible
+ property variant test7: DelegateModel.selectedIndex
+ property variant test8: DelegateModel.inSelected
+ property variant test9: DelegateModel.groups
+
+ function hide() { DelegateModel.inVisible = false }
+ function select() { DelegateModel.inSelected = true }
Item {
Package.name: "package"
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/groups.qml b/tests/auto/quick/qquickvisualdatamodel/data/groups.qml
index 7502dd2502..ba9b5e5e1f 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/groups.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/groups.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
ListView {
width: 100
@@ -12,14 +13,14 @@ ListView {
}
model: visualModel
- VisualDataModel {
+ DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: myModel
@@ -31,16 +32,16 @@ ListView {
height: 2
property variant test1: name
property variant test2: index
- property variant test3: VisualDataModel.itemsIndex
- property variant test4: VisualDataModel.inItems
- property variant test5: VisualDataModel.visibleIndex
- property variant test6: VisualDataModel.inVisible
- property variant test7: VisualDataModel.selectedIndex
- property variant test8: VisualDataModel.inSelected
- property variant test9: VisualDataModel.groups
-
- function hide() { VisualDataModel.inVisible = false }
- function select() { VisualDataModel.inSelected = true }
+ property variant test3: DelegateModel.itemsIndex
+ property variant test4: DelegateModel.inItems
+ property variant test5: DelegateModel.visibleIndex
+ property variant test6: DelegateModel.inVisible
+ property variant test7: DelegateModel.selectedIndex
+ property variant test8: DelegateModel.inSelected
+ property variant test9: DelegateModel.groups
+
+ function hide() { DelegateModel.inVisible = false }
+ function select() { DelegateModel.inSelected = true }
}
}
}
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/invalidAttachment.qml b/tests/auto/quick/qquickvisualdatamodel/data/invalidAttachment.qml
index 2758f56d0f..adc52a7281 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/invalidAttachment.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/invalidAttachment.qml
@@ -1,15 +1,16 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Item {
- property VisualDataModel invalidVdm: VisualDataModel.model
+ property DelegateModel invalidVdm: DelegateModel.model
Repeater {
model: 1
delegate: Item {
id: outer
objectName: "delegate"
- property VisualDataModel validVdm: outer.VisualDataModel.model
- property VisualDataModel invalidVdm: inner.VisualDataModel.model
+ property DelegateModel validVdm: outer.DelegateModel.model
+ property DelegateModel invalidVdm: inner.DelegateModel.model
Item {
id: inner
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/itemsDestroyed_package.qml b/tests/auto/quick/qquickvisualdatamodel/data/itemsDestroyed_package.qml
index b47f22dc34..3c61991fcb 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/itemsDestroyed_package.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/itemsDestroyed_package.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Item {
width: 100
@@ -9,7 +10,7 @@ Item {
model: visualModel.parts.list
}
- VisualDataModel {
+ DelegateModel {
id: visualModel
model: myModel
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties-package.qml b/tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties-package.qml
index b6b56727e8..827d6a609e 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties-package.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties-package.qml
@@ -1,17 +1,18 @@
import QtQuick 2.0
+import QtQml.Models 2.12
ListView {
width: 100
height: 100
model: visualModel.parts.package
- VisualDataModel {
+ DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: ListModel {
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties.qml b/tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties.qml
index d2dfc37e07..1c3e07ba4f 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/listmodelproperties.qml
@@ -1,15 +1,16 @@
import QtQuick 2.0
+import QtQml.Models 2.12
ListView {
width: 100
height: 100
- model: VisualDataModel {
+ model: DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: ListModel {
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties-package.qml b/tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties-package.qml
index 964ac426f8..32a7e8571e 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties-package.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties-package.qml
@@ -1,17 +1,18 @@
import QtQuick 2.0
+import QtQml.Models 2.12
import tst_qquickvisualdatamodel 1.0
ListView {
width: 100
height: 100
model: visualModel.parts.package
- VisualDataModel {
+ DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: StandardItemModel {
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties.qml b/tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties.qml
index 77e30b69b9..436aff3da9 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/multipleroleproperties.qml
@@ -1,16 +1,17 @@
import QtQuick 2.0
+import QtQml.Models 2.12
import tst_qquickvisualdatamodel 1.0
ListView {
width: 100
height: 100
- model: VisualDataModel {
+ model: DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: StandardItemModel {
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties-package.qml b/tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties-package.qml
index c69e54c2f8..9b5198068f 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties-package.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties-package.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
import tst_qquickvisualdatamodel 1.0
ListView {
@@ -6,7 +7,7 @@ ListView {
height: 100
model: visualModel.parts.package
- VisualDataModel {
+ DelegateModel {
id: visualModel
objectName: "visualModel"
@@ -18,8 +19,8 @@ ListView {
]
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: objects
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties.qml b/tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties.qml
index 0dbe2f5459..1941cdc6f2 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/objectlistproperties.qml
@@ -1,10 +1,11 @@
import QtQuick 2.0
+import QtQml.Models 2.12
import tst_qquickvisualdatamodel 1.0
ListView {
width: 100
height: 100
- model: VisualDataModel {
+ model: DelegateModel {
id: visualModel
objectName: "visualModel"
@@ -16,8 +17,8 @@ ListView {
]
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: objects
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/onChanged.qml b/tests/auto/quick/qquickvisualdatamodel/data/onChanged.qml
index 71dc7d72d7..4a0d75b0f1 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/onChanged.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/onChanged.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
+import QtQml.Models 2.12
-VisualDataModel {
+DelegateModel {
id: vm
property var inserted
@@ -42,7 +43,7 @@ VisualDataModel {
}
groups: [
- VisualDataGroup {
+ DelegateModelGroup {
id: vi;
property var inserted
@@ -56,7 +57,7 @@ VisualDataModel {
vi.removed = removed
}
},
- VisualDataGroup {
+ DelegateModelGroup {
id: si;
property var inserted
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/packageView.qml b/tests/auto/quick/qquickvisualdatamodel/data/packageView.qml
index e3719a8be0..e6cb856c1e 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/packageView.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/packageView.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
Item {
width: 240
@@ -34,7 +35,7 @@ Item {
}
- VisualDataModel {
+ DelegateModel {
id: visualModel
delegate: myDelegate
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties-package.qml b/tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties-package.qml
index 1af1b3858d..8da63c8d22 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties-package.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties-package.qml
@@ -1,4 +1,5 @@
import QtQuick 2.0
+import QtQml.Models 2.12
import tst_qquickvisualdatamodel 1.0
ListView {
@@ -6,13 +7,13 @@ ListView {
height: 100
model: visualModel.parts.package
- VisualDataModel {
+ DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: SingleRoleModel {
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties.qml b/tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties.qml
index 50a5ded6ff..0c217ca763 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/singleroleproperties.qml
@@ -1,16 +1,17 @@
import QtQuick 2.0
+import QtQml.Models 2.12
import tst_qquickvisualdatamodel 1.0
ListView {
width: 100
height: 100
- model: VisualDataModel {
+ model: DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: SingleRoleModel {
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties-package.qml b/tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties-package.qml
index d1a4604b77..79a4c97b5b 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties-package.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties-package.qml
@@ -1,17 +1,18 @@
import QtQuick 2.0
+import QtQml.Models 2.12
import tst_qquickvisualdatamodel 1.0
ListView {
width: 100
height: 100
model: visualModel.parts.package
- VisualDataModel {
+ DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: [
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties.qml b/tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties.qml
index a075ccb4d9..69de807614 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/stringlistproperties.qml
@@ -1,16 +1,17 @@
import QtQuick 2.0
+import QtQml.Models 2.12
import tst_qquickvisualdatamodel 1.0
ListView {
width: 100
height: 100
- model: VisualDataModel {
+ model: DelegateModel {
id: visualModel
objectName: "visualModel"
groups: [
- VisualDataGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
- VisualDataGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
+ DelegateModelGroup { id: visibleItems; objectName: "visibleItems"; name: "visible"; includeByDefault: true },
+ DelegateModelGroup { id: selectedItems; objectName: "selectedItems"; name: "selected" }
]
model: [
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/visualdatamodel.qml b/tests/auto/quick/qquickvisualdatamodel/data/visualdatamodel.qml
index e3ae1d1772..8779a0bae8 100644
--- a/tests/auto/quick/qquickvisualdatamodel/data/visualdatamodel.qml
+++ b/tests/auto/quick/qquickvisualdatamodel/data/visualdatamodel.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
+import QtQml.Models 2.12
-VisualDataModel {
+DelegateModel {
function setRoot() {
rootIndex = modelIndex(0);
}
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index cabfb97914..fac8283e2c 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -76,13 +76,13 @@ class SingleRoleModel : public QAbstractItemModel
public:
struct Branch;
struct Node {
- Node(const QString &display = QString()) : branch(0), display(display) {}
+ Node(const QString &display = QString()) : branch(nullptr), display(display) {}
Branch *branch;
QString display;
};
struct Branch {
- Branch(Branch *parent = 0) : parent(parent) {}
+ Branch(Branch *parent = nullptr) : parent(parent) {}
~Branch() { foreach (const Node &child, children) delete child.branch; }
int indexOf(Branch *branch) const {
for (int i = 0; i < children.count(); ++i) {
@@ -96,7 +96,7 @@ public:
};
- SingleRoleModel(const QStringList &list = QStringList(), const QByteArray &role = "name", QObject *parent = 0)
+ SingleRoleModel(const QStringList &list = QStringList(), const QByteArray &role = "name", QObject *parent = nullptr)
: QAbstractItemModel(parent), m_role(role)
{
foreach (const QString &string, list)
@@ -255,7 +255,7 @@ class StandardItemModel : public QStandardItemModel
Q_PROPERTY(QQmlListProperty<StandardItem> items READ items CONSTANT)
Q_CLASSINFO("DefaultProperty", "items")
public:
- QQmlListProperty<StandardItem> items() { return QQmlListProperty<StandardItem>(this, 0, append, 0, 0, 0); }
+ QQmlListProperty<StandardItem> items() { return QQmlListProperty<StandardItem>(this, nullptr, append, nullptr, nullptr, nullptr); }
static void append(QQmlListProperty<StandardItem> *property, StandardItem *item)
{
@@ -270,7 +270,7 @@ class DataSubObject : public QObject
Q_PROPERTY(QString subName READ subName WRITE setSubName NOTIFY subNameChanged)
public:
- DataSubObject(QObject *parent=0) : QObject(parent) {}
+ DataSubObject(QObject *parent=nullptr) : QObject(parent) {}
QString subName() const { return m_subName; }
void setSubName(const QString &name) {
@@ -296,8 +296,8 @@ class DataObject : public QObject
Q_PROPERTY(QObject *object READ object)
public:
- DataObject(QObject *parent=0) : QObject(parent) {}
- DataObject(const QString &name, const QString &color, QObject *parent=0)
+ DataObject(QObject *parent=nullptr) : QObject(parent) {}
+ DataObject(const QString &name, const QString &color, QObject *parent=nullptr)
: QObject(parent), m_name(name), m_color(color), m_object(new DataSubObject(this)) { }
@@ -336,11 +336,11 @@ class ItemRequester : public QObject
{
Q_OBJECT
public:
- ItemRequester(QObject *parent = 0)
+ ItemRequester(QObject *parent = nullptr)
: QObject(parent)
- , itemInitialized(0)
- , itemCreated(0)
- , itemDestroyed(0)
+ , itemInitialized(nullptr)
+ , itemCreated(nullptr)
+ , itemDestroyed(nullptr)
, indexInitialized(-1)
, indexCreated(-1)
{
@@ -431,6 +431,7 @@ private slots:
void asynchronousMove_data();
void asynchronousCancel();
void invalidContext();
+ void externalManagedModel();
private:
template <int N> void groups_verify(
@@ -511,7 +512,7 @@ void tst_qquickvisualdatamodel::rootIndex()
engine.rootContext()->setContextProperty("myModel", &model);
QQmlDelegateModel *obj = qobject_cast<QQmlDelegateModel*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QMetaObject::invokeMethod(obj, "setRoot");
QCOMPARE(qvariant_cast<QModelIndex>(obj->rootIndex()), model.index(0,0));
@@ -549,10 +550,10 @@ void tst_qquickvisualdatamodel::updateLayout()
view.setSource(source);
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickText *name = findItem<QQuickText>(contentItem, "display", 0);
QVERIFY(name);
@@ -599,10 +600,10 @@ void tst_qquickvisualdatamodel::childChanged()
view.setSource(source);
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQmlDelegateModel *vdm = listview->findChild<QQmlDelegateModel*>("visualModel");
vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
@@ -624,7 +625,7 @@ void tst_qquickvisualdatamodel::childChanged()
listview->forceLayout();
name = findItem<QQuickText>(contentItem, "display", 1);
- QVERIFY(name != 0);
+ QVERIFY(name != nullptr);
QCOMPARE(name->text(), QString("Row 2 Child Item 2"));
model.item(1,0)->takeRow(1);
@@ -662,10 +663,10 @@ void tst_qquickvisualdatamodel::objectListModel()
view.setSource(testFileUrl("objectlist.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickText *name = findItem<QQuickText>(contentItem, "name", 0);
QCOMPARE(name->text(), QString("Item 1"));
@@ -701,10 +702,10 @@ void tst_qquickvisualdatamodel::singleRole()
view.setSource(testFileUrl("singlerole1.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
QCOMPARE(name->text(), QString("two"));
@@ -723,10 +724,10 @@ void tst_qquickvisualdatamodel::singleRole()
view.setSource(testFileUrl("singlerole2.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
QCOMPARE(name->text(), QString("two"));
@@ -745,10 +746,10 @@ void tst_qquickvisualdatamodel::singleRole()
view.setSource(testFileUrl("singlerole2.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickText *name = findItem<QQuickText>(contentItem, "name", 1);
QCOMPARE(name->text(), QString("two"));
@@ -771,10 +772,10 @@ void tst_qquickvisualdatamodel::modelProperties()
view.setSource(testFileUrl("modelproperties.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
QVERIFY(delegate);
@@ -804,10 +805,10 @@ void tst_qquickvisualdatamodel::modelProperties()
view.setSource(testFileUrl("modelproperties.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
QVERIFY(delegate);
@@ -833,10 +834,10 @@ void tst_qquickvisualdatamodel::modelProperties()
view.setSource(testFileUrl("modelproperties.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 0);
QVERIFY(delegate);
@@ -875,10 +876,10 @@ void tst_qquickvisualdatamodel::modelProperties()
view.setSource(source);
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQuickItem *delegate = findItem<QQuickItem>(contentItem, "delegate", 1);
QVERIFY(delegate);
@@ -917,13 +918,13 @@ void tst_qquickvisualdatamodel::noDelegate()
view.setSource(source);
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQmlDelegateModel *vdm = listview->findChild<QQmlDelegateModel*>("visualModel");
- QVERIFY(vdm != 0);
+ QVERIFY(vdm != nullptr);
QCOMPARE(vdm->count(), 3);
- vdm->setDelegate(0);
+ vdm->setDelegate(nullptr);
QCOMPARE(vdm->count(), 0);
}
@@ -955,7 +956,7 @@ void tst_qquickvisualdatamodel::itemsDestroyed()
QVERIFY(delegate = findItem<QQuickItem>(view.contentItem(), "delegate", 1));
}
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QVERIFY(!delegate);
}
@@ -975,16 +976,16 @@ void tst_qquickvisualdatamodel::packagesDestroyed()
qApp->processEvents();
QQuickListView *leftview = findItem<QQuickListView>(view.rootObject(), "leftList");
- QTRY_VERIFY(leftview != 0);
+ QTRY_VERIFY(leftview != nullptr);
QQuickListView *rightview = findItem<QQuickListView>(view.rootObject(), "rightList");
- QTRY_VERIFY(rightview != 0);
+ QTRY_VERIFY(rightview != nullptr);
QQuickItem *leftContent = leftview->contentItem();
- QTRY_VERIFY(leftContent != 0);
+ QTRY_VERIFY(leftContent != nullptr);
QQuickItem *rightContent = rightview->contentItem();
- QTRY_VERIFY(rightContent != 0);
+ QTRY_VERIFY(rightContent != nullptr);
leftview->forceLayout();
rightview->forceLayout();
@@ -1052,7 +1053,7 @@ void tst_qquickvisualdatamodel::qaimRowsMoved()
engine.rootContext()->setContextProperty("myModel", &model);
QQmlDelegateModel *obj = qobject_cast<QQmlDelegateModel*>(c.create());
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QSignalSpy spy(obj, SIGNAL(modelUpdated(QQmlChangeSet,bool)));
model.emitMove(sourceFirst, sourceLast, destinationChild);
@@ -1213,11 +1214,11 @@ void tst_qquickvisualdatamodel::watchedRoles()
QQmlDelegateModel *vdm = qobject_cast<QQmlDelegateModel*>(object.data());
QVERIFY(vdm);
- // VisualDataModel doesn't initialize model data until the first item is requested.
+ // DelegateModel doesn't initialize model data until the first item is requested.
QQuickItem *item = qobject_cast<QQuickItem*>(vdm->object(0));
QVERIFY(item);
vdm->release(item);
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // Ensure released items are deleted before test exits.
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // Ensure released items are deleted before test exits.
QSignalSpy spy(vdm, SIGNAL(modelUpdated(QQmlChangeSet,bool)));
QQmlChangeSet changeSet;
@@ -1305,7 +1306,7 @@ void tst_qquickvisualdatamodel::hasModelChildren()
QCOMPARE(vdm->count(), 4);
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
item = qobject_cast<QQuickItem*>(vdm->object(0));
QVERIFY(item);
@@ -1326,7 +1327,7 @@ void tst_qquickvisualdatamodel::hasModelChildren()
QVERIFY(item);
QCOMPARE(item->property("modelChildren").toBool(), false);
vdm->release(item);
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // Ensure released items are deleted before test exits.
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // Ensure released items are deleted before test exits.
QCOMPARE(vdm->stringValue(0, QLatin1String("hasModelChildren")), QVariant(true).toString());
QCOMPARE(vdm->stringValue(1, QLatin1String("hasModelChildren")), QVariant(false).toString());
@@ -1355,7 +1356,7 @@ void tst_qquickvisualdatamodel::setValue()
QCOMPARE(vdm->count(), 3);
- QQuickItem *item = 0;
+ QQuickItem *item = nullptr;
item = qobject_cast<QQuickItem*>(vdm->object(0));
QVERIFY(item);
@@ -1366,7 +1367,7 @@ void tst_qquickvisualdatamodel::setValue()
vdm->release(item);
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // Ensure released items are deleted before test exits.
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // Ensure released items are deleted before test exits.
}
void tst_qquickvisualdatamodel::remove_data()
@@ -1406,10 +1407,10 @@ void tst_qquickvisualdatamodel::remove()
view.setSource(testFileUrl("groups.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(qvariant_cast<QObject *>(listview->model()));
QVERIFY(visualModel);
@@ -1456,22 +1457,22 @@ void tst_qquickvisualdatamodel::remove()
QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
}
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: remove: index out of range");
evaluate<void>(visualModel, "items.remove(-8, 4)");
QCOMPARE(listview->count(), 7);
QCOMPARE(visualModel->items()->count(), 7);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: remove: index out of range");
evaluate<void>(visualModel, "items.remove(12, 2)");
QCOMPARE(listview->count(), 7);
QCOMPARE(visualModel->items()->count(), 7);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: remove: invalid count");
evaluate<void>(visualModel, "items.remove(5, 3)");
QCOMPARE(listview->count(), 7);
QCOMPARE(visualModel->items()->count(), 7);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: remove: invalid count");
evaluate<void>(visualModel, "items.remove(5, -2)");
QCOMPARE(listview->count(), 7);
QCOMPARE(visualModel->items()->count(), 7);
@@ -1515,10 +1516,10 @@ void tst_qquickvisualdatamodel::move()
view.setSource(testFileUrl("groups.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(qvariant_cast<QObject *>(listview->model()));
QVERIFY(visualModel);
@@ -1593,37 +1594,37 @@ void tst_qquickvisualdatamodel::move()
QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
}
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: move: invalid count");
evaluate<void>(visualModel, "items.move(5, 2, -2)");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: move: from index out of range");
evaluate<void>(visualModel, "items.move(-6, 2, 1)");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: move: from index out of range");
evaluate<void>(visualModel, "items.move(15, 2, 1)");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: move: from index out of range");
evaluate<void>(visualModel, "items.move(11, 1, 3)");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: move: to index out of range");
evaluate<void>(visualModel, "items.move(2, -5, 1)");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: move: to index out of range");
evaluate<void>(visualModel, "items.move(2, 14, 1)");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: move: to index out of range");
evaluate<void>(visualModel, "items.move(2, 11, 4)");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
@@ -1704,10 +1705,10 @@ void tst_qquickvisualdatamodel::groups()
view.setSource(source);
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQmlDelegateModel *visualModel = listview->findChild<QQmlDelegateModel *>("visualModel");
QVERIFY(visualModel);
@@ -1786,82 +1787,82 @@ void tst_qquickvisualdatamodel::groups()
static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
VERIFY_GROUPS;
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: addGroups: invalid count");
evaluate<void>(visualModel, "items.addGroups(11, -4, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: addGroups: index out of range");
evaluate<void>(visualModel, "items.addGroups(-1, 3, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: addGroups: index out of range");
evaluate<void>(visualModel, "items.addGroups(14, 3, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: addGroups: invalid count");
evaluate<void>(visualModel, "items.addGroups(11, 5, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: setGroups: invalid count");
evaluate<void>(visualModel, "items.setGroups(11, -4, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: setGroups: index out of range");
evaluate<void>(visualModel, "items.setGroups(-1, 3, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: setGroups: index out of range");
evaluate<void>(visualModel, "items.setGroups(14, 3, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: setGroups: invalid count");
evaluate<void>(visualModel, "items.setGroups(11, 5, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: removeGroups: invalid count");
evaluate<void>(visualModel, "items.removeGroups(11, -4, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: removeGroups: index out of range");
evaluate<void>(visualModel, "items.removeGroups(-1, 3, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: removeGroups: index out of range");
evaluate<void>(visualModel, "items.removeGroups(14, 3, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
QCOMPARE(visibleItems->count(), 9);
QCOMPARE(selectedItems->count(), 2);
} {
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: invalid count");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: removeGroups: invalid count");
evaluate<void>(visualModel, "items.removeGroups(11, 5, \"items\")");
QCOMPARE(listview->count(), 12);
QCOMPARE(visualModel->items()->count(), 12);
@@ -2024,10 +2025,10 @@ void tst_qquickvisualdatamodel::get()
view.setSource(testFileUrl("groups.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(qvariant_cast<QObject *>(listview->model()));
QVERIFY(visualModel);
@@ -2038,9 +2039,6 @@ void tst_qquickvisualdatamodel::get()
QQmlDelegateModelGroup *selectedItems = visualModel->findChild<QQmlDelegateModelGroup *>("selectedItems");
QVERIFY(selectedItems);
- QV8Engine *v8Engine = QQmlEnginePrivate::getV8Engine(ctxt->engine());
- QVERIFY(v8Engine);
-
const bool f = false;
const bool t = true;
@@ -2153,7 +2151,7 @@ void tst_qquickvisualdatamodel::get()
void tst_qquickvisualdatamodel::invalidGroups()
{
QUrl source = testFileUrl("groups-invalid.qml");
- QTest::ignoreMessage(QtWarningMsg, (source.toString() + ":12:9: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("Group names must start with a lower case letter")).toUtf8());
+ QTest::ignoreMessage(QtWarningMsg, (source.toString() + ":13:9: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("Group names must start with a lower case letter")).toUtf8());
QQmlComponent component(&engine, source);
QScopedPointer<QObject> object(component.create());
@@ -2320,10 +2318,10 @@ void tst_qquickvisualdatamodel::create()
view.setSource(testFileUrl("create.qml"));
QQuickListView *listview = qobject_cast<QQuickListView*>(view.rootObject());
- QVERIFY(listview != 0);
+ QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
- QVERIFY(contentItem != 0);
+ QVERIFY(contentItem != nullptr);
QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(qvariant_cast<QObject *>(listview->model()));
QVERIFY(visualModel);
@@ -2334,35 +2332,35 @@ void tst_qquickvisualdatamodel::create()
// persistedItems.includeByDefault is true, so all items belong to persistedItems initially.
QVERIFY(delegate = findItem<QQuickItem>(contentItem, "delegate", 1));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), true);
// changing include by default doesn't remove persistance.
evaluate<void>(visualModel, "persistedItems.includeByDefault = false");
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), true);
// removing from persistedItems does.
evaluate<void>(visualModel, "persistedItems.remove(0, 20)");
QCOMPARE(listview->count(), 20);
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), false);
// Request an item instantiated by the view.
QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(1)")));
QCOMPARE(delegate.data(), findItem<QQuickItem>(contentItem, "delegate", 1));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), true);
QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
- evaluate<void>(delegate, "VisualDataModel.inPersistedItems = false");
+ evaluate<void>(delegate, "DelegateModel.inPersistedItems = false");
QCOMPARE(listview->count(), 20);
QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete);
QVERIFY(delegate);
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), false);
QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
// Request an item not instantiated by the view.
QVERIFY(!findItem<QQuickItem>(contentItem, "delegate", 15));
QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(15)")));
QCOMPARE(delegate.data(), findItem<QQuickItem>(contentItem, "delegate", 15));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), true);
QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
evaluate<void>(visualModel, "persistedItems.remove(0)");
@@ -2374,28 +2372,28 @@ void tst_qquickvisualdatamodel::create()
QVERIFY(!findItem<QQuickItem>(contentItem, "delegate", 16));
QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(16)")));
QCOMPARE(delegate.data(), findItem<QQuickItem>(contentItem, "delegate", 16));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), true);
QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
evaluate<void>(listview, "positionViewAtIndex(19, ListView.End)");
QCOMPARE(listview->count(), 20);
- evaluate<void>(delegate, "VisualDataModel.groups = [\"items\"]");
+ evaluate<void>(delegate, "DelegateModel.groups = [\"items\"]");
QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete);
QVERIFY(delegate);
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), false);
QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
// Request and release an item instantiated by the view, then scroll the view so it releases it.
QVERIFY(findItem<QQuickItem>(contentItem, "delegate", 17));
QVERIFY(delegate = qobject_cast<QQuickItem *>(evaluate<QObject *>(visualModel, "items.create(17)")));
QCOMPARE(delegate.data(), findItem<QQuickItem>(contentItem, "delegate", 17));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), true);
QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
evaluate<void>(visualModel, "items.removeGroups(17, \"persistedItems\")");
QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete);
QVERIFY(delegate);
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), false);
QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
evaluate<void>(listview, "positionViewAtIndex(1, ListView.Beginning)");
QCOMPARE(listview->count(), 20);
@@ -2410,7 +2408,7 @@ void tst_qquickvisualdatamodel::create()
evaluate<void>(listview, "positionViewAtIndex(19, ListView.End)");
QCOMPARE(listview->count(), 20);
QVERIFY(delegate = findItem<QQuickItem>(contentItem, "delegate", 18));
- QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(delegate, "DelegateModel.inPersistedItems"), true);
QCoreApplication::sendPostedEvents(delegate, QEvent::DeferredDelete);
QVERIFY(delegate);
evaluate<void>(listview, "positionViewAtIndex(1, ListView.Beginning)");
@@ -2431,11 +2429,11 @@ void tst_qquickvisualdatamodel::create()
void tst_qquickvisualdatamodel::incompleteModel()
{
- // VisualDataModel is first populated in componentComplete. Verify various functions are
+ // DelegateModel is first populated in componentComplete. Verify various functions are
// harmlessly ignored until then.
QQmlComponent component(&engine);
- component.setData("import QtQuick 2.0\n VisualDataModel {}", testFileUrl(""));
+ component.setData("import QtQuick 2.0\nimport QtQml.Models 2.2\nDelegateModel {}", testFileUrl(""));
QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
@@ -2465,7 +2463,7 @@ void tst_qquickvisualdatamodel::incompleteModel()
QCOMPARE(itemsSpy.count(), 0);
QCOMPARE(persistedItemsSpy.count(), 0);
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: get: index out of range");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML DelegateModelGroup: get: index out of range");
QVERIFY(evaluate<bool>(model, "items.get(0) === undefined"));
component.completeCreate();
@@ -2999,7 +2997,7 @@ void tst_qquickvisualdatamodel::insert_data()
"items.get(2).model.modelData = \"seven\"; }")
<< 4 << 5 << 0 << true << false << false << false << false
<< QString("modelData")
- << (QStringList() << "eight" << "one" << "two" << "three" << "four");
+ << (QStringList() << "eight" << "one" << "seven" << "three" << "four");
QTest::newRow("StringList.create prepend modelData")
<< stringListSource[i]
@@ -3116,16 +3114,16 @@ void tst_qquickvisualdatamodel::insert()
QCOMPARE(evaluate<QString>(item, "test6"), propertyData.at(i));
}
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inItems"), true);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inPersistedItems"), false);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inVisible"), true);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inSelected"), false);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.isUnresolved"), false);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inItems"), true);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inVisible"), true);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inSelected"), false);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.isUnresolved"), false);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.itemsIndex"), itemsIndex);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.persistedItemsIndex"), persisted && i > index ? 1 : 0);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.visibleIndex"), visible || i <= index ? i : i - 1);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.selectedIndex"), selected && i > index ? 1 : 0);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.itemsIndex"), itemsIndex);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.persistedItemsIndex"), persisted && i > index ? 1 : 0);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.visibleIndex"), visible || i <= index ? i : i - 1);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.selectedIndex"), selected && i > index ? 1 : 0);
} else if (inItems) {
get = QString("items.get(%1)").arg(index);
} else if (persisted) {
@@ -3154,7 +3152,7 @@ void tst_qquickvisualdatamodel::insert()
QCOMPARE(evaluate<int>(visualModel, get + ".selectedIndex"), selected && i > index ? 1 : 0);
}
- QObject *item = 0;
+ QObject *item = nullptr;
if (inItems)
item = evaluate<QObject *>(visualModel, QString("items.create(%1)").arg(index));
@@ -3179,16 +3177,16 @@ void tst_qquickvisualdatamodel::insert()
QCOMPARE(evaluate<QString>(item, "test6"), propertyData.at(index));
}
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inItems"), inItems);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inPersistedItems"), true);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inVisible"), visible);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inSelected"), selected);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.isUnresolved"), true);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inItems"), inItems);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inVisible"), visible);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inSelected"), selected);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.isUnresolved"), true);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.itemsIndex"), index);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.persistedItemsIndex"), 0);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.visibleIndex"), index);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.selectedIndex"), 0);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.itemsIndex"), index);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.persistedItemsIndex"), 0);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.visibleIndex"), index);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.selectedIndex"), 0);
}
void tst_qquickvisualdatamodel::resolve_data()
@@ -3580,16 +3578,16 @@ void tst_qquickvisualdatamodel::resolve()
QCOMPARE(evaluate<QString>(item, "test6"), propertyData.at(i));
}
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inItems"), true);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inPersistedItems"), false);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inVisible"), true);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inSelected"), false);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.isUnresolved"), false);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inItems"), true);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inPersistedItems"), false);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inVisible"), true);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inSelected"), false);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.isUnresolved"), false);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.itemsIndex"), itemsIndex);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.persistedItemsIndex"), persisted && i > index ? 1 : 0);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.visibleIndex"), visible || i <= index ? i : i - 1);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.selectedIndex"), selected && i > index ? 1 : 0);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.itemsIndex"), itemsIndex);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.persistedItemsIndex"), persisted && i > index ? 1 : 0);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.visibleIndex"), visible || i <= index ? i : i - 1);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.selectedIndex"), selected && i > index ? 1 : 0);
} else if (inItems) {
get = QString("items.get(%1)").arg(index);
} else if (persisted) {
@@ -3618,7 +3616,7 @@ void tst_qquickvisualdatamodel::resolve()
QCOMPARE(evaluate<int>(visualModel, get + ".selectedIndex"), selected && i > index ? 1 : 0);
}
- QObject *item = 0;
+ QObject *item = nullptr;
if (inItems)
item = evaluate<QObject *>(visualModel, QString("items.create(%1)").arg(index));
@@ -3643,16 +3641,16 @@ void tst_qquickvisualdatamodel::resolve()
QCOMPARE(evaluate<QString>(item, "test6"), propertyData.at(index));
}
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inItems"), inItems);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inPersistedItems"), true);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inVisible"), visible);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.inSelected"), selected);
- QCOMPARE(evaluate<bool>(item, "delegate.VisualDataModel.isUnresolved"), false);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inItems"), inItems);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inPersistedItems"), true);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inVisible"), visible);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.inSelected"), selected);
+ QCOMPARE(evaluate<bool>(item, "delegate.DelegateModel.isUnresolved"), false);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.itemsIndex"), index);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.persistedItemsIndex"), 0);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.visibleIndex"), index);
- QCOMPARE(evaluate<int>(item, "delegate.VisualDataModel.selectedIndex"), 0);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.itemsIndex"), index);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.persistedItemsIndex"), 0);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.visibleIndex"), index);
+ QCOMPARE(evaluate<int>(item, "delegate.DelegateModel.selectedIndex"), 0);
}
void tst_qquickvisualdatamodel::warnings_data()
@@ -3665,67 +3663,67 @@ void tst_qquickvisualdatamodel::warnings_data()
QTest::newRow("insert < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.insert(-2, {\"number\": \"eight\"})")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("insert: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("insert: index out of range"))
<< 4;
QTest::newRow("insert > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.insert(8, {\"number\": \"eight\"})")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("insert: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("insert: index out of range"))
<< 4;
QTest::newRow("create < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.create(-2, {\"number\": \"eight\"})")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("create: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("create: index out of range"))
<< 4;
QTest::newRow("create > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.create(8, {\"number\": \"eight\"})")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("create: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("create: index out of range"))
<< 4;
QTest::newRow("resolve from < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.resolve(-2, 3)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("resolve: from index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("resolve: from index out of range"))
<< 4;
QTest::newRow("resolve from > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.resolve(8, 3)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("resolve: from index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("resolve: from index out of range"))
<< 4;
QTest::newRow("resolve to < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.resolve(3, -2)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("resolve: to index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("resolve: to index out of range"))
<< 4;
QTest::newRow("resolve to > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.resolve(3, 8)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("resolve: to index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("resolve: to index out of range"))
<< 4;
QTest::newRow("resolve from invalid index")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.resolve(\"two\", 3)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("resolve: from index invalid"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("resolve: from index invalid"))
<< 4;
QTest::newRow("resolve to invalid index")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.resolve(3, \"two\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("resolve: to index invalid"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("resolve: to index invalid"))
<< 4;
QTest::newRow("resolve already resolved item")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.resolve(3, 2)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("resolve: from is not an unresolved item"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("resolve: from is not an unresolved item"))
<< 4;
QTest::newRow("resolve already resolved item")
@@ -3733,193 +3731,193 @@ void tst_qquickvisualdatamodel::warnings_data()
<< QString("{ items.insert(0, {\"number\": \"eight\"});"
"items.insert(1, {\"number\": \"seven\"});"
"items.resolve(0, 1)}")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("resolve: to is not a model item"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("resolve: to is not a model item"))
<< 6;
QTest::newRow("remove index < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.remove(-2, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("remove: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("remove: index out of range"))
<< 4;
QTest::newRow("remove index == length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.remove(4, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("remove: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("remove: index out of range"))
<< 4;
QTest::newRow("remove index > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.remove(9, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("remove: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("remove: index out of range"))
<< 4;
QTest::newRow("remove invalid index")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.remove(\"nine\", 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("remove: invalid index"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("remove: invalid index"))
<< 4;
QTest::newRow("remove count < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.remove(1, -2)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("remove: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("remove: invalid count"))
<< 4;
QTest::newRow("remove index + count > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.remove(2, 4, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("remove: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("remove: invalid count"))
<< 4;
QTest::newRow("addGroups index < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.addGroups(-2, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("addGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("addGroups: index out of range"))
<< 4;
QTest::newRow("addGroups index == length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.addGroups(4, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("addGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("addGroups: index out of range"))
<< 4;
QTest::newRow("addGroups index > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.addGroups(9, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("addGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("addGroups: index out of range"))
<< 4;
QTest::newRow("addGroups count < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.addGroups(1, -2, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("addGroups: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("addGroups: invalid count"))
<< 4;
QTest::newRow("addGroups index + count > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.addGroups(2, 4, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("addGroups: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("addGroups: invalid count"))
<< 4;
QTest::newRow("removeGroups index < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.removeGroups(-2, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("removeGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("removeGroups: index out of range"))
<< 4;
QTest::newRow("removeGroups index == length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.removeGroups(4, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("removeGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("removeGroups: index out of range"))
<< 4;
QTest::newRow("removeGroups index > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.removeGroups(9, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("removeGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("removeGroups: index out of range"))
<< 4;
QTest::newRow("removeGroups count < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.removeGroups(1, -2, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("removeGroups: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("removeGroups: invalid count"))
<< 4;
QTest::newRow("removeGroups index + count > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.removeGroups(2, 4, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("removeGroups: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("removeGroups: invalid count"))
<< 4;
QTest::newRow("setGroups index < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.setGroups(-2, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("setGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("setGroups: index out of range"))
<< 4;
QTest::newRow("setGroups index == length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.setGroups(4, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("setGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("setGroups: index out of range"))
<< 4;
QTest::newRow("setGroups index > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.setGroups(9, 1, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("setGroups: index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("setGroups: index out of range"))
<< 4;
QTest::newRow("setGroups count < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.setGroups(1, -2, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("setGroups: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("setGroups: invalid count"))
<< 4;
QTest::newRow("setGroups index + count > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.setGroups(2, 4, \"selected\")")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("setGroups: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("setGroups: invalid count"))
<< 4;
QTest::newRow("move from < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(-2, 1, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: from index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: from index out of range"))
<< 4;
QTest::newRow("move from == length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(4, 1, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: from index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: from index out of range"))
<< 4;
QTest::newRow("move from > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(9, 1, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: from index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: from index out of range"))
<< 4;
QTest::newRow("move invalid from")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(\"nine\", 1, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: invalid from index"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: invalid from index"))
<< 4;
QTest::newRow("move to < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(1, -2, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: to index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: to index out of range"))
<< 4;
QTest::newRow("move to == length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(1, 4, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: to index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: to index out of range"))
<< 4;
QTest::newRow("move to > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(1, 9, 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: to index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: to index out of range"))
<< 4;
QTest::newRow("move invalid to")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(1, \"nine\", 1)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: invalid to index"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: invalid to index"))
<< 4;
QTest::newRow("move count < 0")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(1, 1, -2)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: invalid count"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: invalid count"))
<< 4;
QTest::newRow("move from + count > length")
<< testFileUrl("listmodelproperties.qml")
<< QString("items.move(2, 1, 4)")
- << ("<Unknown File>: QML VisualDataGroup: " + QQmlDelegateModelGroup::tr("move: from index out of range"))
+ << ("<Unknown File>: QML DelegateModelGroup: " + QQmlDelegateModelGroup::tr("move: from index out of range"))
<< 4;
}
@@ -4013,7 +4011,7 @@ void tst_qquickvisualdatamodel::asynchronousInsert()
connect(visualModel, SIGNAL(createdItem(int,QObject*)), &requester, SLOT(createdItem(int,QObject*)));
connect(visualModel, SIGNAL(destroyingItem(QObject*)), &requester, SLOT(destroyingItem(QObject*)));
- QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, true));
+ QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, QQmlIncubator::Asynchronous));
QVERIFY(!item);
QVERIFY(!requester.itemInitialized);
@@ -4025,7 +4023,7 @@ void tst_qquickvisualdatamodel::asynchronousInsert()
newItems.append(qMakePair(QLatin1String("New item") + QString::number(i), QString(QLatin1String(""))));
model.insertItems(insertIndex, newItems);
- item = qobject_cast<QQuickItem*>(visualModel->object(completeIndex, false));
+ item = qobject_cast<QQuickItem*>(visualModel->object(completeIndex));
QVERIFY(item);
QCOMPARE(requester.itemInitialized, item);
@@ -4078,7 +4076,7 @@ void tst_qquickvisualdatamodel::asynchronousRemove()
connect(visualModel, SIGNAL(createdItem(int,QObject*)), &requester, SLOT(createdItem(int,QObject*)));
connect(visualModel, SIGNAL(destroyingItem(QObject*)), &requester, SLOT(destroyingItem(QObject*)));
- QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, true));
+ QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, QQmlIncubator::Asynchronous));
QVERIFY(!item);
QVERIFY(!requester.itemInitialized);
@@ -4099,7 +4097,7 @@ void tst_qquickvisualdatamodel::asynchronousRemove()
QVERIFY(!requester.itemCreated);
QVERIFY(!requester.itemDestroyed);
} else {
- item = qobject_cast<QQuickItem*>(visualModel->object(completeIndex, false));
+ item = qobject_cast<QQuickItem*>(visualModel->object(completeIndex));
QVERIFY(item);
QCOMPARE(requester.itemInitialized, item);
@@ -4157,7 +4155,7 @@ void tst_qquickvisualdatamodel::asynchronousMove()
connect(visualModel, SIGNAL(createdItem(int,QObject*)), &requester, SLOT(createdItem(int,QObject*)));
connect(visualModel, SIGNAL(destroyingItem(QObject*)), &requester, SLOT(destroyingItem(QObject*)));
- QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, true));
+ QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, QQmlIncubator::Asynchronous));
QVERIFY(!item);
QVERIFY(!requester.itemInitialized);
@@ -4166,7 +4164,7 @@ void tst_qquickvisualdatamodel::asynchronousMove()
model.moveItems(from, to, count);
- item = qobject_cast<QQuickItem*>(visualModel->object(completeIndex, false));
+ item = qobject_cast<QQuickItem*>(visualModel->object(completeIndex));
QVERIFY(item);
@@ -4200,7 +4198,7 @@ void tst_qquickvisualdatamodel::asynchronousCancel()
QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create());
QVERIFY(visualModel);
- QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, true));
+ QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(requestIndex, QQmlIncubator::Asynchronous));
QVERIFY(!item);
QCOMPARE(controller.incubatingObjectCount(), 1);
@@ -4225,7 +4223,7 @@ void tst_qquickvisualdatamodel::invalidContext()
QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create(context.data()));
QVERIFY(visualModel);
- QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(4, false));
+ QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(4));
QVERIFY(item);
visualModel->release(item);
@@ -4233,10 +4231,77 @@ void tst_qquickvisualdatamodel::invalidContext()
model.insertItem(4, "new item", "");
- item = qobject_cast<QQuickItem*>(visualModel->object(4, false));
+ item = qobject_cast<QQuickItem*>(visualModel->object(4));
QVERIFY(!item);
}
+class ObjectsProvider : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> objects READ objects NOTIFY objectsChanged)
+
+public:
+ explicit ObjectsProvider(QObject *parent = nullptr) : QObject(parent) {}
+
+ Q_INVOKABLE void rebuild()
+ {
+ for (auto old: m_objects)
+ old->deleteLater();
+
+ m_objects.clear();
+ emit objectsChanged();
+
+ const int size = std::rand() & 0xff;
+ for (int i = 0; i < size; ++i) {
+ auto newElement = new QObject(this);
+ QQmlEngine::setObjectOwnership(newElement, QQmlEngine::CppOwnership);
+ m_objects.push_back(newElement);
+ }
+ emit objectsChanged();
+ }
+
+ Q_INVOKABLE QQmlListProperty<QObject> objects()
+ {
+ return QQmlListProperty<QObject>(this, nullptr, &ObjectsProvider::listLength,
+ &ObjectsProvider::listAt);
+ }
+
+ static int listLength(QQmlListProperty<QObject> *property)
+ {
+ auto objectsProvider = qobject_cast<ObjectsProvider*>(property->object);
+ return objectsProvider ? objectsProvider->m_objects.length() : 0;
+ }
+
+ static QObject* listAt(QQmlListProperty<QObject> *property, int index)
+ {
+ auto objectsProvider = qobject_cast<ObjectsProvider*>(property->object);
+ return objectsProvider ? objectsProvider->m_objects.at(index) : nullptr;
+ }
+
+signals:
+ void objectsChanged();
+
+private:
+ QList<QObject *> m_objects;
+};
+
+void tst_qquickvisualdatamodel::externalManagedModel()
+{
+ qmlRegisterType<ObjectsProvider>("example", 1, 0, "ObjectsProvider");
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("externalManagedModel.qml"));
+ QVERIFY(component.isReady());
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QVERIFY(object->property("running").toBool());
+
+ // Make sure it runs to completion without crashing.
+ QTRY_VERIFY(!object->property("running").toBool());
+}
+
QTEST_MAIN(tst_qquickvisualdatamodel)
#include "tst_qquickvisualdatamodel.moc"
diff --git a/tests/auto/quick/qquickwindow/BLACKLIST b/tests/auto/quick/qquickwindow/BLACKLIST
new file mode 100644
index 0000000000..bb9f403188
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/BLACKLIST
@@ -0,0 +1,3 @@
+# QTBUG-62177
+[attachedProperty]
+osx
diff --git a/tests/auto/quick/qquickwindow/data/unloadSubWindow.qml b/tests/auto/quick/qquickwindow/data/unloadSubWindow.qml
index bf9df4867d..8c409781d4 100644
--- a/tests/auto/quick/qquickwindow/data/unloadSubWindow.qml
+++ b/tests/auto/quick/qquickwindow/data/unloadSubWindow.qml
@@ -10,8 +10,10 @@ Window {
id: loader2
sourceComponent : Window {
id: inner
- visible: true
- Component.onCompleted: root.transientWindow = inner
+ Component.onCompleted: {
+ root.transientWindow = inner;
+ inner.show();
+ }
}
}
Component.onDestruction: {
diff --git a/tests/auto/quick/qquickwindow/data/windowattached.qml b/tests/auto/quick/qquickwindow/data/windowattached.qml
index 9d61a02452..66083db428 100644
--- a/tests/auto/quick/qquickwindow/data/windowattached.qml
+++ b/tests/auto/quick/qquickwindow/data/windowattached.qml
@@ -19,7 +19,6 @@ Rectangle {
property Window extraWindow: Window {
objectName: "extraWindow"
title: "extra window"
- visible: true
Text {
objectName: "extraWindowText"
anchors.centerIn: parent
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 91d577fb6f..a862604fc1 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -37,6 +37,7 @@
#include <QtQml/QQmlComponent>
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/private/qquickloader_p.h>
+#include <QtQuick/private/qquickmousearea_p.h>
#include "../../shared/util.h"
#include "../shared/visualtestutil.h"
#include "../shared/viewtestutil.h"
@@ -47,6 +48,8 @@
#include <QOpenGLFunctions>
#include <QSGRendererInterface>
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
struct TouchEventData {
QEvent::Type type;
QWidget *widget;
@@ -70,10 +73,10 @@ static QTouchEvent::TouchPoint makeTouchPoint(QQuickItem *item, const QPointF &p
return tp;
}
-static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states = 0,
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states = nullptr,
const QList<QTouchEvent::TouchPoint>& touchPoints = QList<QTouchEvent::TouchPoint>())
{
- TouchEventData d = { type, 0, w, states, touchPoints };
+ TouchEventData d = { type, nullptr, w, states, touchPoints };
return d;
}
static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states, const QTouchEvent::TouchPoint &touchPoint)
@@ -111,7 +114,7 @@ class RootItemAccessor : public QQuickItem
public:
RootItemAccessor()
: m_rootItemDestroyed(false)
- , m_rootItem(0)
+ , m_rootItem(nullptr)
{
}
Q_INVOKABLE QQuickItem *contentItem()
@@ -138,10 +141,11 @@ class TestTouchItem : public QQuickRectangle
{
Q_OBJECT
public:
- TestTouchItem(QQuickItem *parent = 0)
+ TestTouchItem(QQuickItem *parent = nullptr)
: QQuickRectangle(parent), acceptTouchEvents(true), acceptMouseEvents(true),
- mousePressId(0),
- spinLoopWhenPressed(false), touchEventCount(0)
+ mousePressCount(0), mouseMoveCount(0),
+ spinLoopWhenPressed(false), touchEventCount(0),
+ mouseUngrabEventCount(0)
{
border()->setWidth(1);
setAcceptedMouseButtons(Qt::LeftButton);
@@ -153,15 +157,17 @@ public:
setEnabled(true);
setVisible(true);
- lastEvent = makeTouchData(QEvent::None, window(), 0, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
+ lastEvent = makeTouchData(QEvent::None, window(), nullptr, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
lastVelocity = lastVelocityFromMouseMove = QVector2D();
lastMousePos = QPointF();
lastMouseCapabilityFlags = 0;
touchEventCount = 0;
+ mouseMoveCount = 0;
+ mouseUngrabEventCount = 0;
}
- static void clearMousePressCounter()
+ static void clearMouseEventCounters()
{
mousePressNum = mouseMoveNum = mouseReleaseNum = 0;
}
@@ -173,10 +179,13 @@ public:
bool acceptTouchEvents;
bool acceptMouseEvents;
+ bool grabOnRelease = false;
TouchEventData lastEvent;
- int mousePressId;
+ int mousePressCount;
+ int mouseMoveCount;
bool spinLoopWhenPressed;
int touchEventCount;
+ int mouseUngrabEventCount;
QVector2D lastVelocity;
QVector2D lastVelocityFromMouseMove;
QPointF lastMousePos;
@@ -204,7 +213,7 @@ public:
e->ignore();
return;
}
- mousePressId = ++mousePressNum;
+ mousePressCount = ++mousePressNum;
lastMousePos = e->pos();
lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e);
}
@@ -214,7 +223,7 @@ public:
e->ignore();
return;
}
- ++mouseMoveNum;
+ mouseMoveCount = ++mouseMoveNum;
lastVelocityFromMouseMove = QGuiApplicationPrivate::mouseEventVelocity(e);
lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e);
lastMousePos = e->pos();
@@ -230,10 +239,27 @@ public:
lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e);
}
- bool childMouseEventFilter(QQuickItem *, QEvent *event) {
- // TODO Is it a bug if a QTouchEvent comes here?
- if (event->type() == QEvent::MouseButtonPress)
- mousePressId = ++mousePressNum;
+ void mouseUngrabEvent() {
+ ++mouseUngrabEventCount;
+ }
+
+ bool childMouseEventFilter(QQuickItem *item, QEvent *e) {
+ qCDebug(lcTests) << objectName() << "filtering" << e << "ahead of delivery to" << item->metaObject()->className() << item->objectName();
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ mousePressCount = ++mousePressNum;
+ break;
+ case QEvent::MouseButtonRelease:
+ if (grabOnRelease)
+ grabMouse();
+ break;
+ case QEvent::MouseMove:
+ mouseMoveCount = ++mouseMoveNum;
+ break;
+ default:
+ break;
+ }
+
return false;
}
@@ -260,17 +286,81 @@ class ConstantUpdateItem : public QQuickItem
{
Q_OBJECT
public:
- ConstantUpdateItem(QQuickItem *parent = 0) : QQuickItem(parent), iterations(0) {setFlag(ItemHasContents);}
+ ConstantUpdateItem(QQuickItem *parent = nullptr) : QQuickItem(parent), iterations(0) {setFlag(ItemHasContents);}
int iterations;
protected:
QSGNode* updatePaintNode(QSGNode *, UpdatePaintNodeData *){
iterations++;
update();
- return 0;
+ return nullptr;
}
};
+class MouseRecordingWindow : public QQuickWindow
+{
+public:
+ explicit MouseRecordingWindow(QWindow *parent = nullptr) : QQuickWindow(parent) { }
+
+protected:
+ void mousePressEvent(QMouseEvent *event) override {
+ qCDebug(lcTests) << event;
+ m_mouseEvents << *event;
+ QQuickWindow::mousePressEvent(event);
+ }
+ void mouseMoveEvent(QMouseEvent *event) override {
+ qCDebug(lcTests) << event;
+ m_mouseEvents << *event;
+ QQuickWindow::mouseMoveEvent(event);
+ }
+ void mouseReleaseEvent(QMouseEvent *event) override {
+ qCDebug(lcTests) << event;
+ m_mouseEvents << *event;
+ QQuickWindow::mouseReleaseEvent(event);
+ }
+
+public:
+ QList<QMouseEvent> m_mouseEvents;
+};
+
+class MouseRecordingItem : public QQuickItem
+{
+public:
+ MouseRecordingItem(bool acceptTouch, QQuickItem *parent = nullptr)
+ : QQuickItem(parent)
+ , m_acceptTouch(acceptTouch)
+ {
+ setSize(QSizeF(300, 300));
+ setAcceptedMouseButtons(Qt::LeftButton);
+ }
+
+protected:
+ void touchEvent(QTouchEvent* event) override {
+ event->setAccepted(m_acceptTouch);
+ m_touchEvents << *event;
+ qCDebug(lcTests) << "accepted?" << event->isAccepted() << event;
+ }
+ void mousePressEvent(QMouseEvent *event) override {
+ qCDebug(lcTests) << event;
+ m_mouseEvents << *event;
+ }
+ void mouseMoveEvent(QMouseEvent *event) override {
+ qCDebug(lcTests) << event;
+ m_mouseEvents << *event;
+ }
+ void mouseReleaseEvent(QMouseEvent *event) override {
+ qCDebug(lcTests) << event;
+ m_mouseEvents << *event;
+ }
+
+public:
+ QList<QMouseEvent> m_mouseEvents;
+ QList<QTouchEvent> m_touchEvents;
+
+private:
+ bool m_acceptTouch;
+};
+
class tst_qquickwindow : public QQmlDataTest
{
Q_OBJECT
@@ -301,6 +391,7 @@ private slots:
void touchEvent_propagation();
void touchEvent_propagation_data();
void touchEvent_cancel();
+ void touchEvent_cancelClearsMouseGrab();
void touchEvent_reentrant();
void touchEvent_velocity();
@@ -308,6 +399,8 @@ private slots:
void mergeTouchPointLists();
void mouseFromTouch_basic();
+ void synthMouseFromTouch_data();
+ void synthMouseFromTouch();
void clearWindow();
@@ -368,6 +461,7 @@ private slots:
void testHoverChildMouseEventFilter();
void testHoverTimestamp();
+ void test_circleMapItem();
void pointerEventTypeAndPointCount();
@@ -377,6 +471,10 @@ private slots:
void findChild();
+ void testChildMouseEventFilter();
+ void testChildMouseEventFilter_data();
+ void cleanupGrabsOnRelease();
+
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -398,12 +496,12 @@ void tst_qquickwindow::openglContextCreatedSignal()
window.setTitle(QTest::currentTestFunction());
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
if (window.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL)
QSKIP("Skipping OpenGL context test due to not running with OpenGL");
- QVERIFY(spy.size() > 0);
+ QTRY_VERIFY(spy.size() > 0);
QVariant ctx = spy.at(0).at(0);
QCOMPARE(qvariant_cast<QOpenGLContext *>(ctx), window.openglContext());
@@ -414,7 +512,7 @@ void tst_qquickwindow::aboutToStopSignal()
QQuickWindow window;
window.setTitle(QTest::currentTestFunction());
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
QSignalSpy spy(&window, SIGNAL(sceneGraphAboutToStop()));
@@ -449,7 +547,7 @@ void tst_qquickwindow::constantUpdatesOnWindow_data()
window.setTitle(QTest::currentTestFunction());
window.setGeometry(100, 100, 300, 200);
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
const bool threaded = QQuickWindowPrivate::get(&window)->context->thread() != QGuiApplication::instance()->thread();
if (threaded) {
QTest::newRow("blocked, beforeRender") << true << QByteArray(SIGNAL(beforeRendering()));
@@ -486,7 +584,7 @@ void tst_qquickwindow::constantUpdatesOnWindow()
bool ok = connect(&window, signal.constData(), &window, SLOT(update()), Qt::DirectConnection);
Q_ASSERT(ok);
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
FrameCounter counter;
connect(&window, SIGNAL(frameSwapped()), &counter, SLOT(incr()), Qt::DirectConnection);
@@ -507,7 +605,7 @@ void tst_qquickwindow::constantUpdatesOnWindow()
void tst_qquickwindow::touchEvent_basic()
{
- TestTouchItem::clearMousePressCounter();
+ TestTouchItem::clearMouseEventCounters();
QQuickWindow *window = new QQuickWindow;
QScopedPointer<QQuickWindow> cleanup(window);
@@ -533,9 +631,10 @@ void tst_qquickwindow::touchEvent_basic()
topItem->setSize(QSizeF(150, 150));
QPointF pos(10, 10);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false);
// press single point
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(),window).commit();
QQuickTouchUtils::flush(window);
QTRY_COMPARE(topItem->lastEvent.touchPoints.count(), 1);
@@ -545,11 +644,11 @@ void tst_qquickwindow::touchEvent_basic()
// would put the decorated window at that position rather than the window itself.
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
topItem->reset();
- QTest::touchEvent(window, touchDevice).release(0, topItem->mapToScene(pos).toPoint(), window);
+ touchSeq.release(0, topItem->mapToScene(pos).toPoint(), window).commit();
// press multiple points
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window)
- .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(), window)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
@@ -558,35 +657,35 @@ void tst_qquickwindow::touchEvent_basic()
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
topItem->reset();
bottomItem->reset();
- QTest::touchEvent(window, touchDevice).release(0, topItem->mapToScene(pos).toPoint(), window).release(1, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.release(0, topItem->mapToScene(pos).toPoint(), window).release(1, bottomItem->mapToScene(pos).toPoint(), window).commit();
// touch point on top item moves to bottom item, but top item should still receive the event
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.move(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
topItem->reset();
- QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.release(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
// touch point on bottom item moves to top item, but bottom item should still receive the event
- QTest::touchEvent(window, touchDevice).press(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).move(0, topItem->mapToScene(pos).toPoint(), window);
+ touchSeq.move(0, topItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos)));
bottomItem->reset();
- QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.release(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
// a single stationary press on an item shouldn't cause an event
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).stationary(0)
- .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.stationary(0)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); // received press only, not stationary
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
@@ -598,13 +697,13 @@ void tst_qquickwindow::touchEvent_basic()
// cleanup: what is pressed must be released
// Otherwise you will get an assertion failure:
// ASSERT: "itemForTouchPointId.isEmpty()" in file items/qquickwindow.cpp
- QTest::touchEvent(window, touchDevice).release(0, pos.toPoint(), window).release(1, pos.toPoint(), window);
+ touchSeq.release(0, pos.toPoint(), window).release(1, pos.toPoint(), window).commit();
QQuickTouchUtils::flush(window);
// move touch point from top item to bottom, and release
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(),window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(),window);
+ touchSeq.release(0, bottomItem->mapToScene(pos).toPoint(),window).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, window, Qt::TouchPointReleased,
@@ -612,13 +711,13 @@ void tst_qquickwindow::touchEvent_basic()
topItem->reset();
// release while another point is pressed
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
- .press(1, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.press(0, topItem->mapToScene(pos).toPoint(),window)
+ .press(1, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
+ touchSeq.move(0, bottomItem->mapToScene(pos).toPoint(), window).commit();
QQuickTouchUtils::flush(window);
- QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window)
- .stationary(1);
+ touchSeq.release(0, bottomItem->mapToScene(pos).toPoint(), window)
+ .stationary(1).commit();
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
@@ -636,7 +735,7 @@ void tst_qquickwindow::touchEvent_basic()
void tst_qquickwindow::touchEvent_propagation()
{
- TestTouchItem::clearMousePressCounter();
+ TestTouchItem::clearMouseEventCounters();
QFETCH(bool, acceptTouchEvents);
QFETCH(bool, acceptMouseEvents);
@@ -679,9 +778,8 @@ void tst_qquickwindow::touchEvent_propagation()
// single touch to top item, should be received by middle item
QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window);
- QTest::qWait(50);
+ QTRY_COMPARE(middleItem->lastEvent.touchPoints.count(), 1);
QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(middleItem->lastEvent.touchPoints.count(), 1);
QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))));
@@ -690,9 +788,8 @@ void tst_qquickwindow::touchEvent_propagation()
// touch top and middle items, middle item should get both events
QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window)
.press(1, pointInMiddleItem, window);
- QTest::qWait(50);
+ QTRY_COMPARE(middleItem->lastEvent.touchPoints.count(), 2);
QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(middleItem->lastEvent.touchPoints.count(), 2);
QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
(QList<QTouchEvent::TouchPoint>() << makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))
@@ -710,10 +807,9 @@ void tst_qquickwindow::touchEvent_propagation()
// touch top and middle items, bottom item should get all events
QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window)
.press(1, pointInMiddleItem, window);
- QTest::qWait(50);
+ QTRY_COMPARE(bottomItem->lastEvent.touchPoints.count(), 2);
QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
- QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 2);
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
(QList<QTouchEvent::TouchPoint>() << makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos))
<< makeTouchPoint(bottomItem, bottomItem->mapFromItem(middleItem, pos)) )));
@@ -783,7 +879,7 @@ void tst_qquickwindow::touchEvent_propagation_data()
void tst_qquickwindow::touchEvent_cancel()
{
- TestTouchItem::clearMousePressCounter();
+ TestTouchItem::clearMouseEventCounters();
QQuickWindow *window = new QQuickWindow;
QScopedPointer<QQuickWindow> cleanup(window);
@@ -807,7 +903,7 @@ void tst_qquickwindow::touchEvent_cancel()
COMPARE_TOUCH_DATA(item->lastEvent, d);
item->reset();
- QWindowSystemInterface::handleTouchCancelEvent(0, touchDevice);
+ QWindowSystemInterface::handleTouchCancelEvent(nullptr, touchDevice);
QCoreApplication::processEvents();
d = makeTouchData(QEvent::TouchCancel, window);
COMPARE_TOUCH_DATA(item->lastEvent, d);
@@ -815,9 +911,41 @@ void tst_qquickwindow::touchEvent_cancel()
delete item;
}
+void tst_qquickwindow::touchEvent_cancelClearsMouseGrab()
+{
+ TestTouchItem::clearMouseEventCounters();
+
+ QQuickWindow *window = new QQuickWindow;
+ QScopedPointer<QQuickWindow> cleanup(window);
+
+ window->resize(250, 250);
+ window->setPosition(100, 100);
+ window->setTitle(QTest::currentTestFunction());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ TestTouchItem *item = new TestTouchItem(window->contentItem());
+ item->setPosition(QPointF(50, 50));
+ item->setSize(QSizeF(150, 150));
+ item->acceptMouseEvents = true;
+ item->acceptTouchEvents = false;
+
+ QPointF pos(50, 50);
+ QTest::touchEvent(window, touchDevice).press(0, item->mapToScene(pos).toPoint(), window);
+ QCoreApplication::processEvents();
+
+ QTRY_COMPARE(item->mousePressCount, 1);
+ QTRY_COMPARE(item->mouseUngrabEventCount, 0);
+
+ QWindowSystemInterface::handleTouchCancelEvent(nullptr, touchDevice);
+ QCoreApplication::processEvents();
+
+ QTRY_COMPARE(item->mouseUngrabEventCount, 1);
+}
+
void tst_qquickwindow::touchEvent_reentrant()
{
- TestTouchItem::clearMousePressCounter();
+ TestTouchItem::clearMouseEventCounters();
QQuickWindow *window = new QQuickWindow;
QScopedPointer<QQuickWindow> cleanup(window);
@@ -856,7 +984,7 @@ void tst_qquickwindow::touchEvent_reentrant()
void tst_qquickwindow::touchEvent_velocity()
{
- TestTouchItem::clearMousePressCounter();
+ TestTouchItem::clearMouseEventCounters();
QQuickWindow *window = new QQuickWindow;
QScopedPointer<QQuickWindow> cleanup(window);
@@ -871,23 +999,29 @@ void tst_qquickwindow::touchEvent_velocity()
item->setPosition(QPointF(50, 50));
item->setSize(QSizeF(150, 150));
- QList<QWindowSystemInterface::TouchPoint> points;
- QWindowSystemInterface::TouchPoint tp;
- tp.id = 1;
- tp.state = Qt::TouchPointPressed;
- QPoint pos = window->mapToGlobal(item->mapToScene(QPointF(10, 10)).toPoint());
- tp.area = QRectF(pos, QSizeF(4, 4));
+ QList<QTouchEvent::TouchPoint> points;
+ QTouchEvent::TouchPoint tp;
+ tp.setId(1);
+ tp.setState(Qt::TouchPointPressed);
+ const QPointF localPos = item->mapToScene(QPointF(10, 10));
+ const QPointF screenPos = window->mapToGlobal(localPos.toPoint());
+ tp.setPos(localPos);
+ tp.setScreenPos(screenPos);
+ tp.setEllipseDiameters(QSizeF(4, 4));
points << tp;
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
QCOMPARE(item->touchEventCount, 1);
- points[0].state = Qt::TouchPointMoved;
- points[0].area.adjust(5, 5, 5, 5);
+ points[0].setState(Qt::TouchPointMoved);
+ points[0].setPos(localPos + QPointF(5, 5));
+ points[0].setScreenPos(screenPos + QPointF(5, 5));
QVector2D velocity(1.5, 2.5);
- points[0].velocity = velocity;
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].setVelocity(velocity);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
QCOMPARE(item->touchEventCount, 2);
@@ -899,17 +1033,20 @@ void tst_qquickwindow::touchEvent_velocity()
QMatrix4x4 transformMatrix;
transformMatrix.rotate(-90, 0, 0, 1); // counterclockwise
QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D();
- points[0].area.adjust(5, 5, 5, 5);
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].setPos(points[0].pos() + QPointF(5, 5));
+ points[0].setScreenPos(points[0].screenPos() + QPointF(5, 5));
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
QCOMPARE(item->lastVelocity, transformedVelocity);
- QPoint itemLocalPos = item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint();
+ QPoint itemLocalPos = item->mapFromScene(points[0].pos()).toPoint();
QPoint itemLocalPosFromEvent = item->lastEvent.touchPoints[0].pos().toPoint();
QCOMPARE(itemLocalPos, itemLocalPosFromEvent);
- points[0].state = Qt::TouchPointReleased;
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].setState(Qt::TouchPointReleased);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
delete item;
@@ -982,7 +1119,7 @@ void tst_qquickwindow::mouseFromTouch_basic()
// should result in sending mouse events generated from the touch
// with the new event propagation system.
- TestTouchItem::clearMousePressCounter();
+ TestTouchItem::clearMouseEventCounters();
QQuickWindow *window = new QQuickWindow;
QScopedPointer<QQuickWindow> cleanup(window);
window->resize(250, 250);
@@ -997,25 +1134,32 @@ void tst_qquickwindow::mouseFromTouch_basic()
item->setSize(QSizeF(150, 150));
item->acceptTouchEvents = false;
- QList<QWindowSystemInterface::TouchPoint> points;
- QWindowSystemInterface::TouchPoint tp;
- tp.id = 1;
- tp.state = Qt::TouchPointPressed;
- QPoint pos = window->mapToGlobal(item->mapToScene(QPointF(10, 10)).toPoint());
- tp.area = QRectF(pos, QSizeF(4, 4));
+ QList<QTouchEvent::TouchPoint> points;
+ QTouchEvent::TouchPoint tp;
+ tp.setId(1);
+ tp.setState(Qt::TouchPointPressed);
+ const QPointF localPos = item->mapToScene(QPointF(10, 10));
+ const QPointF screenPos = window->mapToGlobal(localPos.toPoint());
+ tp.setPos(localPos);
+ tp.setScreenPos(screenPos);
+ tp.setEllipseDiameters(QSizeF(4, 4));
points << tp;
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
- points[0].state = Qt::TouchPointMoved;
- points[0].area.adjust(5, 5, 5, 5);
+ points[0].setState(Qt::TouchPointMoved);
+ points[0].setPos(localPos + QPointF(5, 5));
+ points[0].setScreenPos(screenPos + QPointF(5, 5));
QVector2D velocity(1.5, 2.5);
- points[0].velocity = velocity;
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].setVelocity(velocity);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
- points[0].state = Qt::TouchPointReleased;
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].setState(Qt::TouchPointReleased);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
@@ -1023,7 +1167,7 @@ void tst_qquickwindow::mouseFromTouch_basic()
QCOMPARE(item->mousePressNum, 1);
QCOMPARE(item->mouseMoveNum, 1);
QCOMPARE(item->mouseReleaseNum, 1);
- QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint());
+ QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(points[0].pos()).toPoint());
QCOMPARE(item->lastVelocityFromMouseMove, velocity);
QVERIFY((item->lastMouseCapabilityFlags & QTouchDevice::Velocity) != 0);
@@ -1032,27 +1176,71 @@ void tst_qquickwindow::mouseFromTouch_basic()
QMatrix4x4 transformMatrix;
transformMatrix.rotate(-90, 0, 0, 1); // counterclockwise
QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D();
- points[0].state = Qt::TouchPointPressed;
- points[0].velocity = velocity;
- points[0].area = QRectF(pos, QSizeF(4, 4));
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].setState(Qt::TouchPointPressed);
+ points[0].setVelocity(velocity);
+ tp.setPos(localPos);
+ tp.setScreenPos(screenPos);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
- points[0].state = Qt::TouchPointMoved;
- points[0].area.adjust(5, 5, 5, 5);
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].setState(Qt::TouchPointMoved);
+ points[0].setPos(localPos + QPointF(5, 5));
+ points[0].setScreenPos(screenPos + QPointF(5, 5));
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
- QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint());
+ QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(points[0].pos()).toPoint());
QCOMPARE(item->lastVelocityFromMouseMove, transformedVelocity);
- points[0].state = Qt::TouchPointReleased;
- QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ points[0].setState(Qt::TouchPointReleased);
+ QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window));
QCoreApplication::processEvents();
QQuickTouchUtils::flush(window);
delete item;
}
+void tst_qquickwindow::synthMouseFromTouch_data()
+{
+ QTest::addColumn<bool>("synthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents
+ QTest::addColumn<bool>("acceptTouch"); // QQuickItem::touchEvent: setAccepted()
+
+ QTest::newRow("no synth, accept") << false << true; // suitable for touch-capable UIs
+ QTest::newRow("no synth, don't accept") << false << false;
+ QTest::newRow("synth and accept") << true << true;
+ QTest::newRow("synth, don't accept") << true << false; // the default
+}
+
+void tst_qquickwindow::synthMouseFromTouch()
+{
+ QFETCH(bool, synthMouse);
+ QFETCH(bool, acceptTouch);
+
+ QCoreApplication::setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, synthMouse);
+ QScopedPointer<MouseRecordingWindow> window(new MouseRecordingWindow);
+ QScopedPointer<MouseRecordingItem> item(new MouseRecordingItem(acceptTouch, nullptr));
+ item->setParentItem(window->contentItem());
+ window->resize(250, 250);
+ window->setPosition(100, 100);
+ window->setTitle(QTest::currentTestFunction());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+
+ QPoint p1 = QPoint(20, 20);
+ QPoint p2 = QPoint(30, 30);
+ QTest::touchEvent(window.data(), touchDevice).press(0, p1, window.data());
+ QTest::touchEvent(window.data(), touchDevice).move(0, p2, window.data());
+ QTest::touchEvent(window.data(), touchDevice).release(0, p2, window.data());
+
+ QCOMPARE(item->m_touchEvents.count(), !synthMouse && !acceptTouch ? 1 : 3);
+ QCOMPARE(item->m_mouseEvents.count(), (acceptTouch || !synthMouse) ? 0 : 3);
+ QCOMPARE(window->m_mouseEvents.count(), 0);
+ for (const QMouseEvent &ev : item->m_mouseEvents)
+ QCOMPARE(ev.source(), Qt::MouseEventSynthesizedByQt);
+}
+
void tst_qquickwindow::clearWindow()
{
QQuickWindow *window = new QQuickWindow;
@@ -1071,7 +1259,7 @@ void tst_qquickwindow::clearWindow()
void tst_qquickwindow::mouseFiltering()
{
- TestTouchItem::clearMousePressCounter();
+ TestTouchItem::clearMouseEventCounters();
QQuickWindow *window = new QQuickWindow;
QScopedPointer<QQuickWindow> cleanup(window);
@@ -1085,6 +1273,11 @@ void tst_qquickwindow::mouseFiltering()
bottomItem->setObjectName("Bottom Item");
bottomItem->setSize(QSizeF(150, 150));
+ TestTouchItem *siblingItem = new TestTouchItem(bottomItem);
+ siblingItem->setObjectName("Sibling of Middle Item");
+ siblingItem->setPosition(QPointF(90, 25));
+ siblingItem->setSize(QSizeF(150, 150));
+
TestTouchItem *middleItem = new TestTouchItem(bottomItem);
middleItem->setObjectName("Middle Item");
middleItem->setPosition(QPointF(50, 50));
@@ -1097,19 +1290,51 @@ void tst_qquickwindow::mouseFiltering()
QPoint pos(100, 100);
- QTest::mousePress(window, Qt::LeftButton, 0, pos);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, pos);
+
+ // Mouse filtering propagates down the stack, so the
+ // correct order is
+ // 1. middleItem filters event
+ // 2. bottomItem filters event
+ // 3. topItem receives event
+ QTRY_COMPARE(middleItem->mousePressCount, 1);
+ QTRY_COMPARE(bottomItem->mousePressCount, 2);
+ QTRY_COMPARE(topItem->mousePressCount, 3);
+ QCOMPARE(siblingItem->mousePressCount, 0);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, pos);
+ topItem->clearMouseEventCounters();
+ middleItem->clearMouseEventCounters();
+ bottomItem->clearMouseEventCounters();
+ siblingItem->clearMouseEventCounters();
+
+ // Repeat, but this time have the top item accept the press
+ topItem->acceptMouseEvents = true;
+
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, pos);
// Mouse filtering propagates down the stack, so the
// correct order is
// 1. middleItem filters event
// 2. bottomItem filters event
// 3. topItem receives event
- QTRY_COMPARE(middleItem->mousePressId, 1);
- QTRY_COMPARE(bottomItem->mousePressId, 2);
- QTRY_COMPARE(topItem->mousePressId, 3);
+ QTRY_COMPARE(middleItem->mousePressCount, 1);
+ QTRY_COMPARE(bottomItem->mousePressCount, 2);
+ QTRY_COMPARE(topItem->mousePressCount, 3);
+ QCOMPARE(siblingItem->mousePressCount, 0);
+
+ pos += QPoint(50, 50);
+ QTest::mouseMove(window, pos);
+
+ // The top item has grabbed, so the move goes there, but again
+ // all the ancestors can filter, even when the mouse is outside their bounds
+ QTRY_COMPARE(middleItem->mouseMoveCount, 1);
+ QTRY_COMPARE(bottomItem->mouseMoveCount, 2);
+ QTRY_COMPARE(topItem->mouseMoveCount, 3);
+ QCOMPARE(siblingItem->mouseMoveCount, 0);
// clean up mouse press state for the next tests
- QTest::mouseRelease(window, Qt::LeftButton, 0, pos);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, pos);
}
void tst_qquickwindow::qmlCreation()
@@ -1177,7 +1402,7 @@ void tst_qquickwindow::defaultState()
QQuickWindow cppWindow;
cppWindow.show();
- QTest::qWaitForWindowExposed(&cppWindow);
+ QVERIFY(QTest::qWaitForWindowExposed(&cppWindow));
QCOMPARE(qmlWindow->windowState(), cppWindow.windowState());
}
@@ -1194,6 +1419,10 @@ void tst_qquickwindow::grab_data()
void tst_qquickwindow::grab()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QFETCH(bool, visible);
QFETCH(bool, alpha);
@@ -1277,44 +1506,6 @@ void tst_qquickwindow::animationsWhileHidden()
QTRY_VERIFY(window->isVisible());
}
-// When running on native Nvidia graphics cards on linux, the
-// distance field glyph pixels have a measurable, but not visible
-// pixel error. Use a custom compare function to avoid
-//
-// This was GT-216 with the ubuntu "nvidia-319" driver package.
-// llvmpipe does not show the same issue.
-//
-bool compareImages(const QImage &ia, const QImage &ib)
-{
- if (ia.size() != ib.size())
- qDebug() << "images are of different size" << ia.size() << ib.size();
- Q_ASSERT(ia.size() == ib.size());
- Q_ASSERT(ia.format() == ib.format());
-
- int w = ia.width();
- int h = ia.height();
- const int tolerance = 5;
- for (int y=0; y<h; ++y) {
- const uint *as= (const uint *) ia.constScanLine(y);
- const uint *bs= (const uint *) ib.constScanLine(y);
- for (int x=0; x<w; ++x) {
- uint a = as[x];
- uint b = bs[x];
-
- // No tolerance for error in the alpha.
- if ((a & 0xff000000) != (b & 0xff000000))
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
- return false;
- }
- }
- return true;
-}
-
void tst_qquickwindow::headless()
{
QQmlEngine engine;
@@ -1368,7 +1559,9 @@ void tst_qquickwindow::headless()
// Verify that the visual output is the same
QImage newContent = window->grabWindow();
- QVERIFY(compareImages(newContent, originalContent));
+ QString errorMessage;
+ QVERIFY2(QQuickVisualTestUtil::compareImages(newContent, originalContent, &errorMessage),
+ qPrintable(errorMessage));
}
void tst_qquickwindow::noUpdateWhenNothingChanges()
@@ -1380,7 +1573,7 @@ void tst_qquickwindow::noUpdateWhenNothingChanges()
QQuickRectangle rect(window.contentItem());
window.showNormal();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
// Many platforms are broken in the sense that that they follow up
// the initial expose with a second expose or more. Let these go
// through before we let the test continue.
@@ -1530,7 +1723,7 @@ void tst_qquickwindow::ownershipRootItem()
QVERIFY(accessor);
engine.collectGarbage();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
QVERIFY(!accessor->isRootItemDestroyed());
}
@@ -1637,7 +1830,7 @@ void tst_qquickwindow::cursor()
QCOMPARE(window.cursor().shape(), Qt::WaitCursor);
// Try with the mouse pressed.
- QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100, 100));
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
QTest::mouseMove(&window, QPoint(20, 20));
QCOMPARE(window.cursor().shape(), Qt::IBeamCursor);
QTest::mouseMove(&window, QPoint(125, 125));
@@ -1648,12 +1841,12 @@ void tst_qquickwindow::cursor()
QCOMPARE(window.cursor().shape(), Qt::ArrowCursor);
QTest::mouseMove(&window, QPoint(100, 100));
QCOMPARE(window.cursor().shape(), Qt::WaitCursor);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100, 100));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
// Remove the cursor item from the scene. Theoretically this should make parentItem the
// cursorItem, but given the situation will correct itself after the next mouse move it
// simply unsets the window cursor for now.
- childItem.setParentItem(0);
+ childItem.setParentItem(nullptr);
QCOMPARE(window.cursor().shape(), Qt::ArrowCursor);
parentItem.setCursor(Qt::SizeAllCursor);
@@ -1669,7 +1862,7 @@ void tst_qquickwindow::cursor()
QCOMPARE(childItem.cursor().shape(), Qt::ArrowCursor);
QCOMPARE(window.cursor().shape(), Qt::ArrowCursor);
- QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100, 101));
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(100, 101));
QCOMPARE(window.cursor().shape(), Qt::SizeAllCursor);
}
#endif
@@ -1690,8 +1883,8 @@ void tst_qquickwindow::hideThenDelete()
QFETCH(bool, persistentSG);
QFETCH(bool, persistentGL);
- QSignalSpy *openglDestroyed = 0;
- QSignalSpy *sgInvalidated = 0;
+ QSignalSpy *openglDestroyed = nullptr;
+ QSignalSpy *sgInvalidated = nullptr;
{
QQuickWindow window;
@@ -1705,7 +1898,7 @@ void tst_qquickwindow::hideThenDelete()
window.resize(400, 300);
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
const bool threaded = QQuickWindowPrivate::get(&window)->context->thread() != QGuiApplication::instance()->thread();
const bool isGL = window.rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL;
#if QT_CONFIG(opengl)
@@ -1829,7 +2022,7 @@ void tst_qquickwindow::requestActivate()
QString warning = QString::fromLatin1("Mouse event MousePress not accepted by receiving window");
QWARN(warning.toLatin1().data());
}
- me = QMouseEvent(QEvent::MouseButtonPress, pos, window1->mapToGlobal(pos), Qt::LeftButton, 0, Qt::NoModifier);
+ me = QMouseEvent(QEvent::MouseButtonPress, pos, window1->mapToGlobal(pos), Qt::LeftButton, nullptr, Qt::NoModifier);
QSpontaneKeyEvent::setSpontaneous(&me);
if (!qApp->notify(window1.data(), &me)) {
QString warning = QString::fromLatin1("Mouse event MouseRelease not accepted by receiving window");
@@ -1855,15 +2048,20 @@ void tst_qquickwindow::testWindowVisibilityOrder()
QVERIFY(window2);
QVERIFY(window3);
- QTest::qWaitForWindowExposed(window3);
+ QVERIFY(QTest::qWaitForWindowExposed(window3));
QWindowList windows = QGuiApplication::topLevelWindows();
QTRY_COMPARE(windows.size(), 5);
- QCOMPARE(window3, QGuiApplication::focusWindow());
- QVERIFY(window1->isActive());
- QVERIFY(window2->isActive());
- QVERIFY(window3->isActive());
+ if (qgetenv("XDG_CURRENT_DESKTOP") == "Unity" && QGuiApplication::focusWindow() != window3) {
+ qDebug() << "Unity (flaky QTBUG-62604): expected window3 to have focus; actual focusWindow:"
+ << QGuiApplication::focusWindow();
+ } else {
+ QCOMPARE(window3, QGuiApplication::focusWindow());
+ QVERIFY(window1->isActive());
+ QVERIFY(window2->isActive());
+ QVERIFY(window3->isActive());
+ }
//Test if window4 is shown 2 seconds after the application startup
//with window4 visible window5 (transient child) should also become visible
@@ -1872,7 +2070,7 @@ void tst_qquickwindow::testWindowVisibilityOrder()
window4->setVisible(true);
- QTest::qWaitForWindowExposed(window5);
+ QVERIFY(QTest::qWaitForWindowExposed(window5));
QVERIFY(window4->isVisible());
QVERIFY(window5->isVisible());
}
@@ -1886,7 +2084,7 @@ void tst_qquickwindow::blockClosing()
QVERIFY(!window.isNull());
window->setTitle(QTest::currentTestFunction());
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QVERIFY(window->isVisible());
QWindowSystemInterface::handleCloseEvent(window.data());
QVERIFY(window->isVisible());
@@ -1906,7 +2104,7 @@ void tst_qquickwindow::blockCloseMethod()
QVERIFY(!window.isNull());
window->setTitle(QTest::currentTestFunction());
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QVERIFY(window->isVisible());
QVERIFY(QMetaObject::invokeMethod(window.data(), "close", Qt::DirectConnection));
QVERIFY(window->isVisible());
@@ -1927,7 +2125,7 @@ void tst_qquickwindow::crashWhenHoverItemDeleted()
QVERIFY(!window.isNull());
window->setTitle(QTest::currentTestFunction());
window->show();
- QTest::qWaitForWindowActive(window.data());
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
// Simulate a move from the first rectangle to the second. Crash will happen in here
// Moving instantaneously from (0, 99) to (0, 102) does not cause the crash
@@ -1946,10 +2144,10 @@ void tst_qquickwindow::unloadSubWindow()
QVERIFY(!window.isNull());
window->setTitle(QTest::currentTestFunction());
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QPointer<QQuickWindow> transient;
QTRY_VERIFY(transient = window->property("transientWindow").value<QQuickWindow*>());
- QTest::qWaitForWindowExposed(transient);
+ QVERIFY(QTest::qWaitForWindowExposed(transient));
// Unload the inner window (in nested Loaders) and make sure it doesn't crash
QQuickLoader *loader = window->property("loader1").value<QQuickLoader*>();
@@ -1967,13 +2165,13 @@ void tst_qquickwindow::changeVisibilityInCompleted()
QVERIFY(!window.isNull());
window->setTitle(QTest::currentTestFunction());
window->show();
- QTest::qWaitForWindowExposed(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QPointer<QQuickWindow> winVisible;
QTRY_VERIFY(winVisible = window->property("winVisible").value<QQuickWindow*>());
QPointer<QQuickWindow> winVisibility;
QTRY_VERIFY(winVisibility = window->property("winVisibility").value<QQuickWindow*>());
- QTest::qWaitForWindowExposed(winVisible);
- QTest::qWaitForWindowExposed(winVisibility);
+ QVERIFY(QTest::qWaitForWindowExposed(winVisible));
+ QVERIFY(QTest::qWaitForWindowExposed(winVisibility));
QVERIFY(winVisible->isVisible());
QCOMPARE(winVisibility->visibility(), QWindow::Windowed);
@@ -2152,8 +2350,10 @@ void tst_qquickwindow::defaultSurfaceFormat()
// Depth and stencil should be >= what has been requested. For real. But use
// the context since the window's surface format is only partially updated
// on most platforms.
- QVERIFY(window.openglContext()->format().depthBufferSize() >= 16);
- QVERIFY(window.openglContext()->format().stencilBufferSize() >= 8);
+ const QOpenGLContext *openglContext = nullptr;
+ QTRY_VERIFY((openglContext = window.openglContext()) != nullptr);
+ QVERIFY(openglContext->format().depthBufferSize() >= 16);
+ QVERIFY(openglContext->format().stencilBufferSize() >= 8);
#endif
QSurfaceFormat::setDefaultFormat(savedDefaultFormat);
}
@@ -2173,6 +2373,7 @@ void tst_qquickwindow::attachedProperty()
QQuickWindow *innerWindow = view.rootObject()->findChild<QQuickWindow*>("extraWindow");
QVERIFY(innerWindow);
+ innerWindow->show();
innerWindow->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(innerWindow));
@@ -2184,7 +2385,7 @@ void tst_qquickwindow::attachedProperty()
QCOMPARE(text->property("windowHeight").toInt(), innerWindow->height());
QCOMPARE(text->property("window").value<QQuickWindow*>(), innerWindow);
- text->setParentItem(0);
+ text->setParentItem(nullptr);
QVERIFY(!text->property("contentItem").value<QQuickItem*>());
QCOMPARE(text->property("windowWidth").toInt(), 0);
QCOMPARE(text->property("windowHeight").toInt(), 0);
@@ -2207,7 +2408,7 @@ public:
class GlRenderJob : public QRunnable
{
public:
- GlRenderJob(GLubyte *buf) : readPixel(buf), mutex(0), condition(0) {}
+ GlRenderJob(GLubyte *buf) : readPixel(buf), mutex(nullptr), condition(nullptr) {}
~GlRenderJob() {}
void run() {
QOpenGLContext::currentContext()->functions()->glClearColor(1.0f, 0, 0, 1.0f);
@@ -2272,6 +2473,9 @@ void tst_qquickwindow::testRenderJob()
window.scheduleRenderJob(new RenderJob(QQuickWindow::NoStage, &completedJobs),
QQuickWindow::NoStage);
QTRY_COMPARE(RenderJob::deleted, 1);
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "NoStage job fails on offscreen/minimimal platforms", Continue);
QCOMPARE(completedJobs.size(), 1);
#if QT_CONFIG(opengl)
@@ -2315,7 +2519,7 @@ void tst_qquickwindow::testRenderJob()
class EventCounter : public QQuickRectangle
{
public:
- EventCounter(QQuickItem *parent = 0)
+ EventCounter(QQuickItem *parent = nullptr)
: QQuickRectangle(parent)
{ }
@@ -2340,13 +2544,13 @@ public:
m_childMouseEventFilterEventCount.clear();
}
protected:
- bool childMouseEventFilter(QQuickItem *, QEvent *event) Q_DECL_OVERRIDE
+ bool childMouseEventFilter(QQuickItem *, QEvent *event) override
{
m_childMouseEventFilterEventCount[event->type()]++;
return m_returnTrueForType.contains(event->type());
}
- bool event(QEvent *event) Q_DECL_OVERRIDE
+ bool event(QEvent *event) override
{
m_eventCount[event->type()]++;
return QQuickRectangle::event(event);
@@ -2423,7 +2627,7 @@ class HoverTimestampConsumer : public QQuickItem
{
Q_OBJECT
public:
- HoverTimestampConsumer(QQuickItem *parent = 0)
+ HoverTimestampConsumer(QQuickItem *parent = nullptr)
: QQuickItem(parent)
{
setAcceptHoverEvents(true);
@@ -2503,6 +2707,84 @@ void tst_qquickwindow::testHoverTimestamp()
QCOMPARE(hoverConsumer->hoverTimestamps.last(), 5UL);
}
+class CircleItem : public QQuickRectangle
+{
+public:
+ CircleItem(QQuickItem *parent = nullptr) : QQuickRectangle(parent) { }
+
+ void setRadius(qreal radius) {
+ const qreal diameter = radius*2;
+ setWidth(diameter);
+ setHeight(diameter);
+ }
+
+ bool childMouseEventFilter(QQuickItem *item, QEvent *event) override
+ {
+ Q_UNUSED(item)
+ if (event->type() == QEvent::MouseButtonPress && !contains(static_cast<QMouseEvent*>(event)->pos())) {
+ // This is an evil hack: in case of items that are not rectangles, we never accept the event.
+ // Instead the events are now delivered to QDeclarativeGeoMapItemBase which doesn't to anything with them.
+ // The map below it still works since it filters events and steals the events at some point.
+ event->setAccepted(false);
+ return true;
+ }
+ return false;
+ }
+
+ bool contains(const QPointF &pos) const override {
+ // returns true if the point is inside the the embedded circle inside the (square) rect
+ const float radius = (float)width()/2;
+ const QVector2D center(radius, radius);
+ const QVector2D dx = QVector2D(pos) - center;
+ const bool ret = dx.lengthSquared() < radius*radius;
+ return ret;
+ }
+};
+
+void tst_qquickwindow::test_circleMapItem()
+{
+ QQuickWindow window;
+
+ window.resize(250, 250);
+ window.setPosition(100, 100);
+ window.setTitle(QTest::currentTestFunction());
+
+ QQuickItem *root = window.contentItem();
+ QQuickMouseArea *mab = new QQuickMouseArea(root);
+ mab->setObjectName("Bottom MouseArea");
+ mab->setSize(QSizeF(100, 100));
+
+ CircleItem *topItem = new CircleItem(root);
+ topItem->setFiltersChildMouseEvents(true);
+ topItem->setColor(Qt::green);
+ topItem->setObjectName("Top Item");
+ topItem->setPosition(QPointF(30, 30));
+ topItem->setRadius(20);
+ QQuickMouseArea *mat = new QQuickMouseArea(topItem);
+ mat->setObjectName("Top Item/MouseArea");
+ mat->setSize(QSizeF(40, 40));
+
+ QSignalSpy bottomSpy(mab, SIGNAL(clicked(QQuickMouseEvent *)));
+ QSignalSpy topSpy(mat, SIGNAL(clicked(QQuickMouseEvent *)));
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QTest::qWait(1000);
+
+ QPoint pos(50, 50);
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::KeyboardModifiers(), pos);
+
+ QCOMPARE(topSpy.count(), 1);
+ QCOMPARE(bottomSpy.count(), 0);
+
+ // Outside the "Circles" "input area", but on top of the bottomItem rectangle
+ pos = QPoint(66, 66);
+ QTest::mouseClick(&window, Qt::LeftButton, Qt::KeyboardModifiers(), pos);
+
+ QCOMPARE(bottomSpy.count(), 1);
+ QCOMPARE(topSpy.count(), 1);
+}
+
void tst_qquickwindow::pointerEventTypeAndPointCount()
{
QPointF localPosition(33, 66);
@@ -2516,20 +2798,18 @@ void tst_qquickwindow::pointerEventTypeAndPointCount()
QQuickPointerMouseEvent pme;
pme.reset(&me);
- QVERIFY(pme.isValid());
QCOMPARE(pme.asMouseEvent(localPosition), &me);
QVERIFY(pme.asPointerMouseEvent());
QVERIFY(!pme.asPointerTouchEvent());
QVERIFY(!pme.asPointerTabletEvent());
// QVERIFY(!pe->asTabletEvent()); // TODO
QCOMPARE(pme.pointCount(), 1);
- QCOMPARE(pme.point(0)->scenePos(), scenePosition);
+ QCOMPARE(pme.point(0)->scenePosition(), scenePosition);
QCOMPARE(pme.asMouseEvent(localPosition)->localPos(), localPosition);
QCOMPARE(pme.asMouseEvent(localPosition)->screenPos(), screenPosition);
QQuickPointerTouchEvent pte;
pte.reset(&te);
- QVERIFY(pte.isValid());
QCOMPARE(pte.asTouchEvent(), &te);
QVERIFY(!pte.asPointerMouseEvent());
QVERIFY(pte.asPointerTouchEvent());
@@ -2576,7 +2856,7 @@ class TestDropTarget : public QQuickItem
{
Q_OBJECT
public:
- TestDropTarget(QQuickItem *parent = 0)
+ TestDropTarget(QQuickItem *parent = nullptr)
: QQuickItem(parent)
, enterDropAction(Qt::CopyAction)
, moveDropAction(Qt::CopyAction)
@@ -2637,10 +2917,10 @@ public:
~DragEventTester() {
qDeleteAll(events);
events.clear();
- enterEvent = 0;
- moveEvent = 0;
- dropEvent = 0;
- leaveEvent = 0;
+ enterEvent = nullptr;
+ moveEvent = nullptr;
+ dropEvent = nullptr;
+ leaveEvent = nullptr;
}
void addEnterEvent()
@@ -2849,6 +3129,400 @@ void tst_qquickwindow::findChild()
QCOMPARE(window.contentItem()->findChild<QObject *>("contentItemChild"), contentItemChild);
}
+class DeliveryRecord : public QPair<QString, QString>
+{
+public:
+ DeliveryRecord(const QString &filter, const QString &receiver) : QPair(filter, receiver) { }
+ DeliveryRecord(const QString &receiver) : QPair(QString(), receiver) { }
+ DeliveryRecord() : QPair() { }
+ QString toString() const {
+ if (second.isEmpty())
+ return QLatin1String("Delivery(no receiver)");
+ else if (first.isEmpty())
+ return QString(QLatin1String("Delivery(to '%1')")).arg(second);
+ else
+ return QString(QLatin1String("Delivery('%1' filtering for '%2')")).arg(first).arg(second);
+ }
+};
+
+Q_DECLARE_METATYPE(DeliveryRecord)
+
+QDebug operator<<(QDebug dbg, const DeliveryRecord &pair)
+{
+ dbg << pair.toString();
+ return dbg;
+}
+
+typedef QVector<DeliveryRecord> DeliveryRecordVector;
+
+class EventItem : public QQuickRectangle
+{
+ Q_OBJECT
+public:
+ EventItem(QQuickItem *parent)
+ : QQuickRectangle(parent)
+ , m_eventAccepts(true)
+ , m_filterReturns(true)
+ , m_filterAccepts(true)
+ , m_filterNotPreAccepted(false)
+ {
+ QSizeF psize(parent->width(), parent->height());
+ psize -= QSizeF(20, 20);
+ setWidth(psize.width());
+ setHeight(psize.height());
+ setPosition(QPointF(10, 10));
+ }
+
+ void setFilterReturns(bool filterReturns) { m_filterReturns = filterReturns; }
+ void setFilterAccepts(bool accepts) { m_filterAccepts = accepts; }
+ void setEventAccepts(bool accepts) { m_eventAccepts = accepts; }
+
+ /*!
+ * \internal
+ *
+ * returns false if any of the calls to childMouseEventFilter had the wrong
+ * preconditions. If all calls had the expected precondition, returns true.
+ */
+ bool testFilterPreConditions() const { return !m_filterNotPreAccepted; }
+ static QVector<DeliveryRecord> &deliveryList() { return m_deliveryList; }
+ static QSet<QEvent::Type> &includedEventTypes()
+ {
+ if (m_includedEventTypes.isEmpty())
+ m_includedEventTypes << QEvent::MouseButtonPress;
+ return m_includedEventTypes;
+ }
+ static void setExpectedDeliveryList(const QVector<DeliveryRecord> &v) { m_expectedDeliveryList = v; }
+
+protected:
+ bool childMouseEventFilter(QQuickItem *i, QEvent *e) override
+ {
+ appendEvent(this, i, e);
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ if (!e->isAccepted())
+ m_filterNotPreAccepted = true;
+ e->setAccepted(m_filterAccepts);
+ // qCDebug(lcTests) << objectName() << i->objectName();
+ return m_filterReturns;
+ default:
+ break;
+ }
+ return QQuickRectangle::childMouseEventFilter(i, e);
+ }
+
+ bool event(QEvent *e) override
+ {
+ appendEvent(nullptr, this, e);
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ // qCDebug(lcTests) << objectName();
+ e->setAccepted(m_eventAccepts);
+ return true;
+ default:
+ break;
+ }
+ return QQuickRectangle::event(e);
+ }
+
+private:
+ static void appendEvent(QQuickItem *filter, QQuickItem *receiver, QEvent *event) {
+ if (includedEventTypes().contains(event->type())) {
+ auto record = DeliveryRecord(filter ? filter->objectName() : QString(), receiver ? receiver->objectName() : QString());
+ int i = m_deliveryList.count();
+ if (m_expectedDeliveryList.count() > i && m_expectedDeliveryList[i] == record)
+ qCDebug(lcTests).noquote().nospace() << i << ": " << record;
+ else
+ qCDebug(lcTests).noquote().nospace() << i << ": " << record
+ << ", expected " << (m_expectedDeliveryList.count() > i ? m_expectedDeliveryList[i].toString() : QLatin1String("nothing")) << " <---";
+ m_deliveryList << record;
+ }
+ }
+ bool m_eventAccepts;
+ bool m_filterReturns;
+ bool m_filterAccepts;
+ bool m_filterNotPreAccepted;
+
+ // list of (filtering-parent . receiver) pairs
+ static DeliveryRecordVector m_expectedDeliveryList;
+ static DeliveryRecordVector m_deliveryList;
+ static QSet<QEvent::Type> m_includedEventTypes;
+};
+
+DeliveryRecordVector EventItem::m_expectedDeliveryList;
+DeliveryRecordVector EventItem::m_deliveryList;
+QSet<QEvent::Type> EventItem::m_includedEventTypes;
+
+typedef QVector<const char*> CharStarVector;
+
+Q_DECLARE_METATYPE(CharStarVector)
+
+struct InputState {
+ struct {
+ // event() behavior
+ bool eventAccepts;
+ // filterChildMouse behavior
+ bool returns;
+ bool accepts;
+ bool filtersChildMouseEvent;
+ } r[4];
+};
+
+Q_DECLARE_METATYPE(InputState)
+
+void tst_qquickwindow::testChildMouseEventFilter_data()
+{
+ // HIERARCHY:
+ // r0->r1->r2->r3
+ //
+ QTest::addColumn<QPoint>("mousePos");
+ QTest::addColumn<InputState>("inputState");
+ QTest::addColumn<DeliveryRecordVector>("expectedDeliveryOrder");
+
+ QTest::newRow("if filtered and rejected, do not deliver it to the item that filtered it")
+ << QPoint(100, 100)
+ << InputState({
+ // | event() | child mouse filter
+ // +---------+---------+---------+---------
+ { // | accepts | returns | accepts | filtersChildMouseEvent
+ { false, false, false, false},
+ { true, false, false, false},
+ { false, true, false, true},
+ { false, false, false, false}
+ }
+ })
+ << (DeliveryRecordVector()
+ << DeliveryRecord("r2", "r3")
+ //<< DeliveryRecord("r3") // it got filtered -> do not deliver
+ // DeliveryRecord("r2") // r2 filtered it -> do not deliver
+ << DeliveryRecord("r1")
+ );
+
+ QTest::newRow("no filtering, no accepting")
+ << QPoint(100, 100)
+ << InputState({
+ // | event() | child mouse filter
+ // +---------+---------+---------+---------
+ { // | accepts | returns | accepts | filtersChildMouseEvent
+ { false, false, false, false},
+ { false , false, false, false},
+ { false, false, false, false},
+ { false, false, false, false}
+ }
+ })
+ << (DeliveryRecordVector()
+ << DeliveryRecord("r3")
+ << DeliveryRecord("r2")
+ << DeliveryRecord("r1")
+ << DeliveryRecord("r0")
+ << DeliveryRecord("root")
+ );
+
+ QTest::newRow("all filtering, no accepting")
+ << QPoint(100, 100)
+ << InputState({
+ // | event() | child mouse filter
+ // +---------+---------+---------+---------
+ { // | accepts | returns | accepts | filtersChildMouseEvent
+ { false, false, false, true},
+ { false, false, false, true},
+ { false, false, false, true},
+ { false, false, false, true}
+ }
+ })
+ << (DeliveryRecordVector()
+ << DeliveryRecord("r2", "r3")
+ << DeliveryRecord("r1", "r3")
+ << DeliveryRecord("r0", "r3")
+ << DeliveryRecord("r3")
+ << DeliveryRecord("r1", "r2")
+ << DeliveryRecord("r0", "r2")
+ << DeliveryRecord("r2")
+ << DeliveryRecord("r0", "r1")
+ << DeliveryRecord("r1")
+ << DeliveryRecord("r0")
+ << DeliveryRecord("root")
+ );
+
+
+ QTest::newRow("some filtering, no accepting")
+ << QPoint(100, 100)
+ << InputState({
+ // | event() | child mouse filter
+ // +---------+---------+---------+---------
+ { // | accepts | returns | accepts | filtersChildMouseEvent
+ { false, false, false, true},
+ { false, false, false, true},
+ { false, false, false, false},
+ { false, false, false, false}
+ }
+ })
+ << (DeliveryRecordVector()
+ << DeliveryRecord("r1", "r3")
+ << DeliveryRecord("r0", "r3")
+ << DeliveryRecord("r3")
+ << DeliveryRecord("r1", "r2")
+ << DeliveryRecord("r0", "r2")
+ << DeliveryRecord("r2")
+ << DeliveryRecord("r0", "r1")
+ << DeliveryRecord("r1")
+ << DeliveryRecord("r0")
+ << DeliveryRecord("root")
+ );
+
+ QTest::newRow("r1 accepts")
+ << QPoint(100, 100)
+ << InputState({
+ // | event() | child mouse filter
+ // +---------+---------+---------+---------
+ { // | accepts | returns | accepts | filtersChildMouseEvent
+ { false, false, false, true},
+ { true , false, false, true},
+ { false, false, false, false},
+ { false, false, false, false}
+ }
+ })
+ << (DeliveryRecordVector()
+ << DeliveryRecord("r1", "r3")
+ << DeliveryRecord("r0", "r3")
+ << DeliveryRecord("r3")
+ << DeliveryRecord("r1", "r2")
+ << DeliveryRecord("r0", "r2")
+ << DeliveryRecord("r2")
+ << DeliveryRecord("r0", "r1")
+ << DeliveryRecord("r1")
+ );
+
+ QTest::newRow("r1 rejects and filters")
+ << QPoint(100, 100)
+ << InputState({
+ // | event() | child mouse filter
+ // +---------+---------+---------+---------
+ { // | accepts | returns | accepts | filtersChildMouseEvent
+ { false, false, false, true},
+ { false , true, false, true},
+ { false, false, false, false},
+ { false, false, false, false}
+ }
+ })
+ << (DeliveryRecordVector()
+ << DeliveryRecord("r1", "r3")
+ << DeliveryRecord("r0", "r3")
+// << DeliveryRecord("r3") // since it got filtered we don't deliver to r3
+ << DeliveryRecord("r1", "r2")
+ << DeliveryRecord("r0", "r2")
+// << DeliveryRecord("r2" // since it got filtered we don't deliver to r2
+ << DeliveryRecord("r0", "r1")
+// << DeliveryRecord("r1") // since it acted as a filter and returned true, we don't deliver to r1
+ << DeliveryRecord("r0")
+ << DeliveryRecord("root")
+ );
+
+}
+
+void tst_qquickwindow::testChildMouseEventFilter()
+{
+ QFETCH(QPoint, mousePos);
+ QFETCH(InputState, inputState);
+ QFETCH(DeliveryRecordVector, expectedDeliveryOrder);
+
+ EventItem::setExpectedDeliveryList(expectedDeliveryOrder);
+
+ QQuickWindow window;
+ window.resize(500, 809);
+ QQuickItem *root = window.contentItem();
+ root->setAcceptedMouseButtons(Qt::LeftButton);
+
+ root->setObjectName("root");
+ EventFilter *rootFilter = new EventFilter;
+ root->installEventFilter(rootFilter);
+
+ // Create 4 items; each item a child of the previous item.
+ EventItem *r[4];
+ r[0] = new EventItem(root);
+ r[0]->setColor(QColor(0x404040));
+ r[0]->setWidth(200);
+ r[0]->setHeight(200);
+
+ r[1] = new EventItem(r[0]);
+ r[1]->setColor(QColor(0x606060));
+
+ r[2] = new EventItem(r[1]);
+ r[2]->setColor(Qt::red);
+
+ r[3] = new EventItem(r[2]);
+ r[3]->setColor(Qt::green);
+
+ for (uint i = 0; i < sizeof(r)/sizeof(EventItem*); ++i) {
+ r[i]->setEventAccepts(inputState.r[i].eventAccepts);
+ r[i]->setFilterReturns(inputState.r[i].returns);
+ r[i]->setFilterAccepts(inputState.r[i].accepts);
+ r[i]->setFiltersChildMouseEvents(inputState.r[i].filtersChildMouseEvent);
+ r[i]->setObjectName(QString::fromLatin1("r%1").arg(i));
+ r[i]->setAcceptedMouseButtons(Qt::LeftButton);
+ }
+
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+
+ DeliveryRecordVector &actualDeliveryOrder = EventItem::deliveryList();
+ actualDeliveryOrder.clear();
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, mousePos);
+
+ // Check if event got delivered to the root item. If so, append it to the list of items the event got delivered to
+ if (rootFilter->events.contains(QEvent::MouseButtonPress))
+ actualDeliveryOrder.append(DeliveryRecord("root"));
+
+ for (int i = 0; i < qMax(actualDeliveryOrder.count(), expectedDeliveryOrder.count()); ++i) {
+ const DeliveryRecord expectedNames = expectedDeliveryOrder.value(i);
+ const DeliveryRecord actualNames = actualDeliveryOrder.value(i);
+ QCOMPARE(actualNames.toString(), expectedNames.toString());
+ }
+
+ for (EventItem *item : r) {
+ QVERIFY(item->testFilterPreConditions());
+ }
+
+ // "restore" mouse state
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, mousePos);
+}
+
+void tst_qquickwindow::cleanupGrabsOnRelease()
+{
+ TestTouchItem::clearMouseEventCounters();
+
+ QQuickWindow *window = new QQuickWindow;
+ QScopedPointer<QQuickWindow> cleanup(window);
+ window->resize(250, 250);
+ window->setPosition(100, 100);
+ window->setTitle(QTest::currentTestFunction());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ TestTouchItem *parent = new TestTouchItem(window->contentItem());
+ parent->setObjectName("parent");
+ parent->setSize(QSizeF(150, 150));
+ parent->acceptMouseEvents = true;
+ parent->grabOnRelease = true;
+
+ TestTouchItem *child = new TestTouchItem(parent);
+ child->setObjectName("child");
+ child->setSize(QSizeF(100, 100));
+ child->acceptMouseEvents = true;
+
+ QPoint pos(80, 80);
+
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, pos);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, pos);
+ // There is an explicit parent->grabMouse on release(!). This means grab changes from child
+ // to parent:
+ // This will emit two ungrab events:
+ // 1. One for the child (due to the explicit call to parent->grabMouse())
+ // 2. One for the parent (since the mouse button was finally released)
+ QCOMPARE(child->mouseUngrabEventCount, 1);
+ QCOMPARE(parent->mouseUngrabEventCount, 1);
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/auto/quick/qquickxmllistmodel/data/empty.xml b/tests/auto/quick/qquickxmllistmodel/data/empty.xml
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/empty.xml
+++ /dev/null
diff --git a/tests/auto/quick/qquickxmllistmodel/data/get.qml b/tests/auto/quick/qquickxmllistmodel/data/get.qml
deleted file mode 100644
index 509da7174b..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/get.qml
+++ /dev/null
@@ -1,61 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- source: "model.xml"
- query: "/Pets/Pet"
- XmlRole { name: "name"; query: "name/string()" }
- XmlRole { name: "type"; query: "type/string()" }
- XmlRole { name: "age"; query: "age/number()" }
- XmlRole { name: "size"; query: "size/string()" }
-
- id: root
-
- property bool preTest: false
- property bool postTest: false
-
- function runPreTest() {
- if (root.get(0) != undefined)
- return;
-
- preTest = true;
- }
-
- function runPostTest() {
- if (root.get(-1) != undefined)
- return;
-
- var row = root.get(0);
- if (row.name != "Polly" ||
- row.type != "Parrot" ||
- row.age != 12 ||
- row.size != "Small")
- return;
-
- row = root.get(1);
- if (row.name != "Penny" ||
- row.type != "Turtle" ||
- row.age != 4 ||
- row.size != "Small")
- return;
-
- row = root.get(7);
- if (row.name != "Rover" ||
- row.type != "Dog" ||
- row.age != 0 ||
- row.size != "Large")
- return;
-
- row = root.get(8);
- if (row.name != "Tiny" ||
- row.type != "Elephant" ||
- row.age != 15 ||
- row.size != "Large")
- return;
-
- if (root.get(9) != undefined)
- return;
-
- postTest = true;
- }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/groups.qml b/tests/auto/quick/qquickxmllistmodel/data/groups.qml
deleted file mode 100644
index c1b574a822..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/groups.qml
+++ /dev/null
@@ -1,10 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- source: "groups.xml"
- query: "//animal[@name='Garfield']/parent::group"
-
- XmlRole { name: "id"; query: "@id/string()" }
- XmlRole { name: "name"; query: "@name/string()" }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/groups.xml b/tests/auto/quick/qquickxmllistmodel/data/groups.xml
deleted file mode 100644
index 5de4d2ec71..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/groups.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<groups version="2.0">
- <group id="1" name="Animals" type="root">
- <group id="11" name="dogs">
- <animal id="111" name="Lassie"/>
- <animal id="112" name="Laika"/>
- <animal id="113" name="Wile E. Coyote" type="fictional"/>
- </group>
- <group id="12" name="cats">
- <animal id="121" name="Garfield" type="fictional"/>
- <animal id="122" name="Sylvester" type="fictional"/>
- </group>
- <group id="13" name="birds">
- <animal id="131" name="Donald Duck" type="fictional"/>
- <animal id="132" name="Phoenix" type="fictional"/>
- </group>
- </group>
-</groups>
diff --git a/tests/auto/quick/qquickxmllistmodel/data/model.qml b/tests/auto/quick/qquickxmllistmodel/data/model.qml
deleted file mode 100644
index 2df3927479..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/model.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- source: "model.xml"
- query: "/Pets/Pet"
- XmlRole { name: "name"; query: "name/string()" }
- XmlRole { name: "type"; query: "type/string()" }
- XmlRole { name: "age"; query: "age/number()" }
- XmlRole { name: "size"; query: "size/string()" }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/model.xml b/tests/auto/quick/qquickxmllistmodel/data/model.xml
deleted file mode 100644
index 40cd6d0432..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/model.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<Pets>
- <Pet>
- <name>Polly</name>
- <type>Parrot</type>
- <age>12</age>
- <size>Small</size>
- </Pet>
- <Pet>
- <name>Penny</name>
- <type>Turtle</type>
- <age>4</age>
- <size>Small</size>
- </Pet>
- <Pet>
- <name>Warren</name>
- <type>Rabbit</type>
- <age>2</age>
- <size>Small</size>
- </Pet>
- <Pet>
- <name>Spot</name>
- <type>Dog</type>
- <age>9</age>
- <size>Medium</size>
- </Pet>
- <Pet>
- <name>Whiskers</name>
- <type>Cat</type>
- <age>2</age>
- <size>Medium</size>
- </Pet>
- <Pet>
- <name>Joey</name>
- <type>Kangaroo</type>
- <age>1</age>
- </Pet>
- <Pet>
- <name>Kimba</name>
- <type>Bunny</type>
- <age>65</age>
- <size>Large</size>
- </Pet>
- <Pet>
- <name>Rover</name>
- <type>Dog</type>
- <size>Large</size>
- </Pet>
- <Pet>
- <name>Tiny</name>
- <type>Elephant</type>
- <age>15</age>
- <size>Large</size>
- </Pet>
-</Pets>
diff --git a/tests/auto/quick/qquickxmllistmodel/data/model2.xml b/tests/auto/quick/qquickxmllistmodel/data/model2.xml
deleted file mode 100644
index dab2ec6dc0..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/model2.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<Pets>
- <Pet>
- <name>Polly</name>
- <type>Parrot</type>
- <age>12</age>
- <size>Small</size>
- </Pet>
- <Pet>
- <name>Penny</name>
- <type>Turtle</type>
- <age>4</age>
- <size>Small</size>
- </Pet>
-</Pets>
diff --git a/tests/auto/quick/qquickxmllistmodel/data/propertychanges.qml b/tests/auto/quick/qquickxmllistmodel/data/propertychanges.qml
deleted file mode 100644
index f8a97bffc3..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/propertychanges.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- source: "model.xml"
- query: "/Pets/Pet"
- XmlRole { objectName: "role"; name: "name"; query: "name/string()" }
- XmlRole { name: "type"; query: "type/string()" }
- XmlRole { name: "age"; query: "age/number()" }
- XmlRole { name: "size"; query: "size/string()" }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/proxyCrash.qml b/tests/auto/quick/qquickxmllistmodel/data/proxyCrash.qml
deleted file mode 100644
index c0c5a25e3c..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/proxyCrash.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-import SortFilterProxyModel 1.0
-
-SortFilterProxyModel {
- source: XmlListModel {
- XmlRole { }
- }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/recipes.qml b/tests/auto/quick/qquickxmllistmodel/data/recipes.qml
deleted file mode 100644
index dc609e95e3..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/recipes.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- source: "recipes.xml"
- query: "/recipes/recipe"
- XmlRole { name: "title"; query: "@title/string()" }
- XmlRole { name: "picture"; query: "picture/string()" }
- XmlRole { name: "ingredients"; query: "ingredients/string()" }
- XmlRole { name: "preparation"; query: "method/string()" }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/recipes.xml b/tests/auto/quick/qquickxmllistmodel/data/recipes.xml
deleted file mode 100644
index d71de60710..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/recipes.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<recipes>
- <recipe title="Pancakes">
- <picture>content/pics/pancakes.jpg</picture>
- <ingredients><![CDATA[<html>
- <ul>
- <li> 1 cup (150g) self-raising flour
- <li> 1 tbs caster sugar
- <li> 3/4 cup (185ml) milk
- <li> 1 egg
- </ul>
- </html>
- ]]></ingredients>
- <method><![CDATA[<html>
- <ol>
- <li> Sift flour and sugar together into a bowl. Add a pinch of salt.
- <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth.
- <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface.
- <li> Turn over and cook other side until golden.
- </ol>
- </html>
- ]]></method>
- </recipe>
- <recipe title="Fruit Salad">
- <picture>content/pics/fruit-salad.jpg</picture>
- <ingredients><![CDATA[* Seasonal Fruit]]></ingredients>
- <method><![CDATA[* Chop fruit and place in a bowl.]]></method>
- </recipe>
- <recipe title="Vegetable Soup">
- <picture>content/pics/vegetable-soup.jpg</picture>
- <ingredients><![CDATA[<html>
- <ul>
- <li> 1 onion
- <li> 1 turnip
- <li> 1 potato
- <li> 1 carrot
- <li> 1 head of celery
- <li> 1 1/2 litres of water
- </ul>
- </html>
- ]]></ingredients>
- <method><![CDATA[<html>
- <ol>
- <li> Chop vegetables.
- <li> Boil in water until vegetables soften.
- <li> Season with salt and pepper to taste.
- </ol>
- </html>
- ]]></method>
- </recipe>
- <recipe title="Hamburger">
- <picture>content/pics/hamburger.jpg</picture>
- <ingredients><![CDATA[<html>
- <ul>
- <li> 500g minced beef
- <li> Seasoning
- <li> lettuce, tomato, onion, cheese
- <li> 1 hamburger bun for each burger
- </ul>
- </html>
- ]]></ingredients>
- <method><![CDATA[<html>
- <ol>
- <li> Mix the beef, together with seasoning, in a food processor.
- <li> Shape the beef into burgers.
- <li> Grill the burgers for about 5 mins on each side (until cooked through)
- <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion.
- </ol>
- </html>
- ]]></method>
- </recipe>
- <recipe title="Lemonade">
- <picture>content/pics/lemonade.jpg</picture>
- <ingredients><![CDATA[<html>
- <ul>
- <li> 1 cup Lemon Juice
- <li> 1 cup Sugar
- <li> 6 Cups of Water (2 cups warm water, 4 cups cold water)
- </ul>
- </html>
- ]]></ingredients>
- <method><![CDATA[<html>
- <ol>
- <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves.
- <li> Pour in lemon juice, stir again, and add 4 cups of cold water.
- <li> Chill or serve over ice cubes.
- </ol>
- </html>
- ]]></method>
- </recipe>
-</recipes>
diff --git a/tests/auto/quick/qquickxmllistmodel/data/roleCrash.qml b/tests/auto/quick/qquickxmllistmodel/data/roleCrash.qml
deleted file mode 100644
index 6a7059bb45..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/roleCrash.qml
+++ /dev/null
@@ -1,8 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- id: model
- XmlRole {}
- Component.onCompleted: model.roles = 0
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/roleErrors.qml b/tests/auto/quick/qquickxmllistmodel/data/roleErrors.qml
deleted file mode 100644
index 91664b6d4a..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/roleErrors.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- source: "model.xml"
- query: "/Pets/Pet"
- XmlRole { name: "name"; query: "/name/string()" } //starts with '/'
- XmlRole { name: "type"; query: "type" } //no type
- XmlRole { name: "age"; query: "age/" } //ends with '/'
- XmlRole { name: "size"; query: "size/number()" } //wrong type
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/roleKeys.qml b/tests/auto/quick/qquickxmllistmodel/data/roleKeys.qml
deleted file mode 100644
index 9f667d86e5..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/roleKeys.qml
+++ /dev/null
@@ -1,13 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- query: "/data/item"
- XmlRole { id: nameRole; name: "name"; query: "name/string()"; isKey: true }
- XmlRole { name: "age"; query: "age/number()"; isKey: true }
- XmlRole { name: "sport"; query: "sport/string()" }
-
- function disableNameKey() {
- nameRole.isKey = false;
- }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/testtypes.qml b/tests/auto/quick/qquickxmllistmodel/data/testtypes.qml
deleted file mode 100644
index 5ec1ffa35f..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/testtypes.qml
+++ /dev/null
@@ -1,8 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- query: "/data"
- XmlRole { name: "stringValue"; query: "a-string/string()" }
- XmlRole { name: "numberValue"; query: "a-number/number()" }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/data/unique.qml b/tests/auto/quick/qquickxmllistmodel/data/unique.qml
deleted file mode 100644
index 322a2e4e5c..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/data/unique.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import QtQuick 2.0
-import QtQuick.XmlListModel 2.0
-
-XmlListModel {
- source: "model.xml"
- query: "/Pets/Pet"
- XmlRole { name: "name"; query: "name/string()" }
- XmlRole { name: "name"; query: "type/string()" }
-}
diff --git a/tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro b/tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro
deleted file mode 100644
index 902325802c..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro
+++ /dev/null
@@ -1,16 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qquickxmllistmodel
-macx:CONFIG -= app_bundle
-
-SOURCES += tst_qquickxmllistmodel.cpp \
- ../../../../src/imports/xmllistmodel/qqmlxmllistmodel.cpp
-HEADERS += ../../../../src/imports/xmllistmodel/qqmlxmllistmodel_p.h
-
-include (../../shared/util.pri)
-
-TESTDATA = data/*
-
-QT += core-private gui-private qml-private network testlib xmlpatterns
-
-OTHER_FILES += \
- data/groups.qml
diff --git a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
deleted file mode 100644
index 757cb8f513..0000000000
--- a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp
+++ /dev/null
@@ -1,1004 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include <QtGlobal>
-#include <math.h>
-#include <QMetaObject>
-#include <qtest.h>
-#include <QtTest/qsignalspy.h>
-#include <QtQml/qqmlnetworkaccessmanagerfactory.h>
-#include <QtNetwork/qnetworkaccessmanager.h>
-#include <QtNetwork/qnetworkrequest.h>
-#include <QtCore/qtimer.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qtemporaryfile.h>
-#include <QtCore/qsortfilterproxymodel.h>
-#include "../../shared/util.h"
-#include <private/qqmlengine_p.h>
-
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlcomponent.h>
-#include "../../../../src/imports/xmllistmodel/qqmlxmllistmodel_p.h"
-
-#include <algorithm>
-
-typedef QPair<int, int> QQuickXmlListRange;
-typedef QList<QVariantList> QQmlXmlModelData;
-
-Q_DECLARE_METATYPE(QList<QQuickXmlListRange>)
-Q_DECLARE_METATYPE(QQmlXmlModelData)
-Q_DECLARE_METATYPE(QQuickXmlListModel::Status)
-
-class tst_qquickxmllistmodel : public QQmlDataTest
-
-{
- Q_OBJECT
-public:
- tst_qquickxmllistmodel() {}
-
-private slots:
- void initTestCase() {
- QQmlDataTest::initTestCase();
- qRegisterMetaType<QQuickXmlListModel::Status>();
- }
-
- void buildModel();
- void testTypes();
- void testTypes_data();
- void cdata();
- void attributes();
- void roles();
- void roleErrors();
- void uniqueRoleNames();
- void headers();
- void xml();
- void xml_data();
- void source();
- void source_data();
- void data();
- void get();
- void reload();
- void useKeys();
- void useKeys_data();
- void noKeysValueChanges();
- void keysChanged();
- void threading();
- void threading_data();
- void propertyChanges();
- void selectAncestor();
-
- void roleCrash();
- void proxyCrash();
-
-private:
- QString errorString(QAbstractItemModel *model) {
- QString ret;
- QMetaObject::invokeMethod(model, "errorString", Q_RETURN_ARG(QString, ret));
- return ret;
- }
-
- QString makeItemXmlAndData(const QString &data, QQmlXmlModelData *modelData = 0) const
- {
- if (modelData)
- modelData->clear();
- QString xml;
-
- if (!data.isEmpty()) {
- QStringList items = data.split(QLatin1Char(';'));
- foreach(const QString &item, items) {
- if (item.isEmpty())
- continue;
- QVariantList variants;
- xml += QLatin1String("<item>");
- QStringList fields = item.split(QLatin1Char(','));
- foreach(const QString &field, fields) {
- QStringList values = field.split(QLatin1Char('='));
- if (values.count() != 2) {
- qWarning() << "makeItemXmlAndData: invalid field:" << field;
- continue;
- }
- xml += QString("<%1>%2</%1>").arg(values[0], values[1]);
- if (!modelData)
- continue;
- bool isNum = false;
- int number = values[1].toInt(&isNum);
- if (isNum)
- variants << number;
- else
- variants << values[1];
- }
- xml += QLatin1String("</item>");
- if (modelData)
- modelData->append(variants);
- }
- }
-
- QString decl = "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>";
- return decl + QLatin1String("<data>") + xml + QLatin1String("</data>");
- }
-
- QQmlEngine engine;
-};
-
-class CustomNetworkAccessManagerFactory : public QObject, public QQmlNetworkAccessManagerFactory
-{
- Q_OBJECT
-public:
- QVariantMap lastSentHeaders;
-
-protected:
- QNetworkAccessManager *create(QObject *parent);
-};
-
-class CustomNetworkAccessManager : public QNetworkAccessManager
-{
- Q_OBJECT
-public:
- CustomNetworkAccessManager(CustomNetworkAccessManagerFactory *factory, QObject *parent)
- : QNetworkAccessManager(parent), m_factory(factory) {}
-
-protected:
- QNetworkReply *createRequest(Operation op, const QNetworkRequest &req, QIODevice * outgoingData = 0)
- {
- if (m_factory) {
- QVariantMap map;
- foreach (const QString &header, req.rawHeaderList())
- map[header] = req.rawHeader(header.toUtf8());
- m_factory->lastSentHeaders = map;
- }
- return QNetworkAccessManager::createRequest(op, req, outgoingData);
- }
-
- QPointer<CustomNetworkAccessManagerFactory> m_factory;
-};
-
-QNetworkAccessManager *CustomNetworkAccessManagerFactory::create(QObject *parent)
-{
- return new CustomNetworkAccessManager(this, parent);
-}
-
-
-void tst_qquickxmllistmodel::buildModel()
-{
- QQmlComponent component(&engine, testFileUrl("model.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 9);
-
- QModelIndex index = model->index(3, 0);
- QCOMPARE(model->data(index, Qt::UserRole).toString(), QLatin1String("Spot"));
- QCOMPARE(model->data(index, Qt::UserRole+1).toString(), QLatin1String("Dog"));
- QCOMPARE(model->data(index, Qt::UserRole+2).toInt(), 9);
- QCOMPARE(model->data(index, Qt::UserRole+3).toString(), QLatin1String("Medium"));
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::testTypes()
-{
- QFETCH(QString, xml);
- QFETCH(QString, roleName);
- QFETCH(QVariant, expectedValue);
-
- QQmlComponent component(&engine, testFileUrl("testtypes.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- model->setProperty("xml",xml.toUtf8());
- QMetaObject::invokeMethod(model, "reload");
- QTRY_COMPARE(model->rowCount(), 1);
-
- int role = model->roleNames().key(roleName.toUtf8(), -1);
- QVERIFY(role >= 0);
-
- QModelIndex index = model->index(0, 0);
- if (expectedValue.toString() == "nan")
- QVERIFY(qIsNaN(model->data(index, role).toDouble()));
- else
- QCOMPARE(model->data(index, role), expectedValue);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::testTypes_data()
-{
- QTest::addColumn<QString>("xml");
- QTest::addColumn<QString>("roleName");
- QTest::addColumn<QVariant>("expectedValue");
-
- QTest::newRow("missing string field") << "<data></data>"
- << "stringValue" << QVariant("");
- QTest::newRow("empty string") << "<data><a-string></a-string></data>"
- << "stringValue" << QVariant("");
- QTest::newRow("1-char string") << "<data><a-string>5</a-string></data>"
- << "stringValue" << QVariant("5");
- QTest::newRow("string ok") << "<data><a-string>abc def g</a-string></data>"
- << "stringValue" << QVariant("abc def g");
-
- QTest::newRow("missing number field") << "<data></data>"
- << "numberValue" << QVariant("");
- double nan = qQNaN();
- QTest::newRow("empty number field") << "<data><a-number></a-number></data>"
- << "numberValue" << QVariant(nan);
- QTest::newRow("number field with string") << "<data><a-number>a string</a-number></data>"
- << "numberValue" << QVariant(nan);
- QTest::newRow("-1") << "<data><a-number>-1</a-number></data>"
- << "numberValue" << QVariant("-1");
- QTest::newRow("-1.5") << "<data><a-number>-1.5</a-number></data>"
- << "numberValue" << QVariant("-1.5");
- QTest::newRow("0") << "<data><a-number>0</a-number></data>"
- << "numberValue" << QVariant("0");
- QTest::newRow("+1") << "<data><a-number>1</a-number></data>"
- << "numberValue" << QVariant("1");
- QTest::newRow("+1.5") << "<data><a-number>1.5</a-number></data>"
- << "numberValue" << QVariant("1.5");
-}
-
-void tst_qquickxmllistmodel::cdata()
-{
- QQmlComponent component(&engine, testFileUrl("recipes.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 5);
-
- QVERIFY(model->data(model->index(2, 0), Qt::UserRole+2).toString().startsWith(QLatin1String("<html>")));
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::attributes()
-{
- QQmlComponent component(&engine, testFileUrl("recipes.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 5);
- QCOMPARE(model->data(model->index(2, 0), Qt::UserRole).toString(), QLatin1String("Vegetable Soup"));
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::roles()
-{
- QQmlComponent component(&engine, testFileUrl("model.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 9);
-
- QHash<int, QByteArray> roleNames = model->roleNames();
- QCOMPARE(roleNames.count(), 4);
- QVERIFY(roleNames.key("name", -1) >= 0);
- QVERIFY(roleNames.key("type", -1) >= 0);
- QVERIFY(roleNames.key("age", -1) >= 0);
- QVERIFY(roleNames.key("size", -1) >= 0);
-
- QSet<int> roles;
- roles.insert(roleNames.key("name"));
- roles.insert(roleNames.key("type"));
- roles.insert(roleNames.key("age"));
- roles.insert(roleNames.key("size"));
- QCOMPARE(roles.count(), 4);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::roleErrors()
-{
- QQmlComponent component(&engine, testFileUrl("roleErrors.qml"));
- QTest::ignoreMessage(QtWarningMsg, (testFileUrl("roleErrors.qml").toString() + ":7:5: QML XmlRole: An XmlRole query must not start with '/'").toUtf8().constData());
- QTest::ignoreMessage(QtWarningMsg, (testFileUrl("roleErrors.qml").toString() + ":10:5: QML XmlRole: invalid query: \"age/\"").toUtf8().constData());
-
- //### make sure we receive all expected warning messages.
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 9);
-
- QModelIndex index = model->index(3, 0);
- //### should any of these return valid values?
- QCOMPARE(model->data(index, Qt::UserRole), QVariant());
- QCOMPARE(model->data(index, Qt::UserRole+1), QVariant());
- QCOMPARE(model->data(index, Qt::UserRole+2), QVariant());
-
- QEXPECT_FAIL("", "QTBUG-10797", Continue);
- QCOMPARE(model->data(index, Qt::UserRole+3), QVariant());
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::uniqueRoleNames()
-{
- QQmlComponent component(&engine, testFileUrl("unique.qml"));
- QTest::ignoreMessage(QtWarningMsg, (testFileUrl("unique.qml").toString() + ":8:5: QML XmlRole: \"name\" duplicates a previous role name and will be disabled.").toUtf8().constData());
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 9);
-
- QHash<int, QByteArray> roleNames = model->roleNames();
- QCOMPARE(roleNames.count(), 1);
-
- delete model;
-}
-
-
-void tst_qquickxmllistmodel::xml()
-{
- QFETCH(QString, xml);
- QFETCH(int, count);
-
- QQmlComponent component(&engine, testFileUrl("model.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
-
- QSignalSpy spy(model, SIGNAL(statusChanged(QQuickXmlListModel::Status)));
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Loading);
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- QTest::qWait(50);
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Ready);
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
- QCOMPARE(model->rowCount(), 9);
-
- // if xml is empty (i.e. clearing) it won't have any effect if a source is set
- if (xml.isEmpty())
- model->setProperty("source",QUrl());
- model->setProperty("xml",xml);
- QCOMPARE(model->property("progress").toDouble(), qreal(1.0)); // immediately goes to 1.0 if using setXml()
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Loading);
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- if (xml.isEmpty())
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Null);
- else
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Ready);
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->rowCount(), count);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::xml_data()
-{
- QTest::addColumn<QString>("xml");
- QTest::addColumn<int>("count");
-
- QTest::newRow("xml with no items") << "<Pets></Pets>" << 0;
- QTest::newRow("empty xml") << "" << 0;
- QTest::newRow("one item") << "<Pets><Pet><name>Hobbes</name><type>Tiger</type><age>7</age><size>Large</size></Pet></Pets>" << 1;
-}
-
-void tst_qquickxmllistmodel::headers()
-{
- // ensure the QNetworkAccessManagers created for this test are immediately deleted
- QQmlEngine qmlEng;
-
- CustomNetworkAccessManagerFactory factory;
- qmlEng.setNetworkAccessManagerFactory(&factory);
-
- QQmlComponent component(&qmlEng, testFileUrl("model.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Ready);
-
- QVariantMap expectedHeaders;
- expectedHeaders["Accept"] = "application/xml,*/*";
-
- QCOMPARE(factory.lastSentHeaders.count(), expectedHeaders.count());
- foreach (const QString &header, expectedHeaders.keys()) {
- QVERIFY(factory.lastSentHeaders.contains(header));
- QCOMPARE(factory.lastSentHeaders[header].toString(), expectedHeaders[header].toString());
- }
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::source()
-{
- QFETCH(QUrl, source);
- QFETCH(int, count);
- QFETCH(QQuickXmlListModel::Status, status);
-
- QQmlComponent component(&engine, testFileUrl("model.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QSignalSpy spy(model, SIGNAL(statusChanged(QQuickXmlListModel::Status)));
-
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Loading);
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Ready);
- QVERIFY(errorString(model).isEmpty());
- QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
- QCOMPARE(model->rowCount(), 9);
-
- model->setProperty("source",source);
- if (model->property("source").toString().isEmpty())
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Null);
- QCOMPARE(model->property("progress").toDouble(), qreal(0.0));
- QTRY_COMPARE(spy.count(), 1); spy.clear();
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")),
- QQuickXmlListModel::Loading);
- QVERIFY(errorString(model).isEmpty());
-
- QEventLoop loop;
- QTimer timer;
- timer.setSingleShot(true);
- connect(model, SIGNAL(statusChanged(QQuickXmlListModel::Status)), &loop, SLOT(quit()));
- connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
- timer.start(20000);
- loop.exec();
-
- if (spy.count() == 0 && status != QQuickXmlListModel::Ready) {
- qWarning("QQuickXmlListModel invalid source test timed out");
- } else {
- QCOMPARE(spy.count(), 1); spy.clear();
- }
-
- QCOMPARE(qvariant_cast<QQuickXmlListModel::Status>(model->property("status")), status);
- QCOMPARE(model->rowCount(), count);
-
- if (status == QQuickXmlListModel::Ready)
- QCOMPARE(model->property("progress").toDouble(), qreal(1.0));
-
- QCOMPARE(errorString(model).isEmpty(), status == QQuickXmlListModel::Ready);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::source_data()
-{
- QTest::addColumn<QUrl>("source");
- QTest::addColumn<int>("count");
- QTest::addColumn<QQuickXmlListModel::Status>("status");
-
- QTest::newRow("valid") << testFileUrl("model2.xml") << 2
- << QQuickXmlListModel::Ready;
- QTest::newRow("invalid") << QUrl("http://blah.blah/blah.xml") << 0
- << QQuickXmlListModel::Error;
-
- // empty file
- QTemporaryFile *temp = new QTemporaryFile(this);
- if (temp->open())
- QTest::newRow("empty file") << QUrl::fromLocalFile(temp->fileName()) << 0
- << QQuickXmlListModel::Ready;
- temp->close();
-}
-
-void tst_qquickxmllistmodel::data()
-{
- QQmlComponent component(&engine, testFileUrl("model.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
-
- for (int i=0; i<9; i++) {
- QModelIndex index = model->index(i, 0);
- for (int j=0; j<model->roleNames().count(); j++) {
- QCOMPARE(model->data(index, j), QVariant());
- }
- }
- QTRY_COMPARE(model->rowCount(), 9);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::get()
-{
- QQmlComponent component(&engine, testFileUrl("get.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
-
- QVERIFY(model != 0);
-
- QVERIFY(QMetaObject::invokeMethod(model, "runPreTest"));
- QCOMPARE(model->property("preTest").toBool(), true);
-
- QTRY_COMPARE(model->rowCount(), 9);
-
- QVERIFY(QMetaObject::invokeMethod(model, "runPostTest"));
- QCOMPARE(model->property("postTest").toBool(), true);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::reload()
-{
- // If no keys are used, the model should be rebuilt from scratch when
- // reload() is called.
-
- QQmlComponent component(&engine, testFileUrl("model.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 9);
-
- QSignalSpy spyInsert(model, SIGNAL(rowsInserted(QModelIndex,int,int)));
- QSignalSpy spyRemove(model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
- QSignalSpy spyCount(model, SIGNAL(countChanged()));
- //reload multiple times to test the xml query aborting
- QMetaObject::invokeMethod(model, "reload");
- QMetaObject::invokeMethod(model, "reload");
- QCoreApplication::processEvents();
- QMetaObject::invokeMethod(model, "reload");
- QMetaObject::invokeMethod(model, "reload");
- QTRY_COMPARE(spyCount.count(), 0);
- QTRY_COMPARE(spyInsert.count(), 1);
- QTRY_COMPARE(spyRemove.count(), 1);
-
- QCOMPARE(spyInsert[0][1].toInt(), 0);
- QCOMPARE(spyInsert[0][2].toInt(), 8);
-
- QCOMPARE(spyRemove[0][1].toInt(), 0);
- QCOMPARE(spyRemove[0][2].toInt(), 8);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::useKeys()
-{
- // If using incremental updates through keys, the model should only
- // insert & remove some of the items, instead of throwing everything
- // away and causing the view to repaint the whole view.
-
- QFETCH(QString, oldXml);
- QFETCH(int, oldCount);
- QFETCH(QString, newXml);
- QFETCH(QQmlXmlModelData, newData);
- QFETCH(QList<QQuickXmlListRange>, insertRanges);
- QFETCH(QList<QQuickXmlListRange>, removeRanges);
-
- QQmlComponent component(&engine, testFileUrl("roleKeys.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
-
- model->setProperty("xml",oldXml);
- QTRY_COMPARE(model->rowCount(), oldCount);
-
- QSignalSpy spyInsert(model, SIGNAL(rowsInserted(QModelIndex,int,int)));
- QSignalSpy spyRemove(model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
- QSignalSpy spyCount(model, SIGNAL(countChanged()));
-
- model->setProperty("xml",newXml);
-
- if (oldCount != newData.count()) {
- QTRY_COMPARE(model->rowCount(), newData.count());
- QCOMPARE(spyCount.count(), 1);
- } else {
- QTRY_VERIFY(spyInsert.count() > 0 || spyRemove.count() > 0);
- QCOMPARE(spyCount.count(), 0);
- }
-
- QList<int> roles = model->roleNames().keys();
- std::sort(roles.begin(), roles.end());
- for (int i=0; i<model->rowCount(); i++) {
- QModelIndex index = model->index(i, 0);
- for (int j=0; j<roles.count(); j++)
- QCOMPARE(model->data(index, roles.at(j)), newData[i][j]);
- }
-
- QCOMPARE(spyInsert.count(), insertRanges.count());
- for (int i=0; i<spyInsert.count(); i++) {
- QCOMPARE(spyInsert[i][1].toInt(), insertRanges[i].first);
- QCOMPARE(spyInsert[i][2].toInt(), insertRanges[i].first + insertRanges[i].second - 1);
- }
-
- QCOMPARE(spyRemove.count(), removeRanges.count());
- for (int i=0; i<spyRemove.count(); i++) {
- QCOMPARE(spyRemove[i][1].toInt(), removeRanges[i].first);
- QCOMPARE(spyRemove[i][2].toInt(), removeRanges[i].first + removeRanges[i].second - 1);
- }
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::useKeys_data()
-{
- QTest::addColumn<QString>("oldXml");
- QTest::addColumn<int>("oldCount");
- QTest::addColumn<QString>("newXml");
- QTest::addColumn<QQmlXmlModelData>("newData");
- QTest::addColumn<QList<QQuickXmlListRange> >("insertRanges");
- QTest::addColumn<QList<QQuickXmlListRange> >("removeRanges");
-
- QQmlXmlModelData modelData;
-
- QTest::newRow("append 1")
- << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(1, 1))
- << QList<QQuickXmlListRange>();
-
- QTest::newRow("append multiple")
- << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(1, 2))
- << QList<QQuickXmlListRange>();
-
- QTest::newRow("insert in different spots")
- << makeItemXmlAndData("name=B,age=35,sport=Athletics") << 1
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2))
- << QList<QQuickXmlListRange>();
-
- QTest::newRow("insert in middle")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=D,age=55,sport=Golf") << 2
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(1, 2))
- << QList<QQuickXmlListRange>();
-
- QTest::newRow("remove first")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics") << 2
- << makeItemXmlAndData("name=B,age=35,sport=Athletics", &modelData)
- << modelData
- << QList<QQuickXmlListRange>()
- << (QList<QQuickXmlListRange>() << qMakePair(0, 1));
-
- QTest::newRow("remove last")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics") << 2
- << makeItemXmlAndData("name=A,age=25,sport=Football", &modelData)
- << modelData
- << QList<QQuickXmlListRange>()
- << (QList<QQuickXmlListRange>() << qMakePair(1, 1));
-
- QTest::newRow("remove from multiple spots")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing") << 5
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=C,age=45,sport=Curling", &modelData)
- << modelData
- << QList<QQuickXmlListRange>()
- << (QList<QQuickXmlListRange>() << qMakePair(1, 1) << qMakePair(3,2));
-
- QTest::newRow("remove all")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling") << 3
- << makeItemXmlAndData("", &modelData)
- << modelData
- << QList<QQuickXmlListRange>()
- << (QList<QQuickXmlListRange>() << qMakePair(0, 3));
-
- QTest::newRow("replace item")
- << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
- << makeItemXmlAndData("name=ZZZ,age=25,sport=Football", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(0, 1))
- << (QList<QQuickXmlListRange>() << qMakePair(0, 1));
-
- QTest::newRow("add and remove simultaneously, in different spots")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf") << 4
- << makeItemXmlAndData("name=B,age=35,sport=Athletics;name=E,age=65,sport=Fencing", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(1, 1))
- << (QList<QQuickXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2));
-
- QTest::newRow("insert at start, remove at end i.e. rss feed")
- << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing") << 3
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(0, 2))
- << (QList<QQuickXmlListRange>() << qMakePair(1, 2));
-
- QTest::newRow("remove at start, insert at end")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling") << 3
- << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(1, 2))
- << (QList<QQuickXmlListRange>() << qMakePair(0, 2));
-
- QTest::newRow("all data has changed")
- << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35") << 2
- << makeItemXmlAndData("name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
- << modelData
- << (QList<QQuickXmlListRange>() << qMakePair(0, 2))
- << (QList<QQuickXmlListRange>() << qMakePair(0, 2));
-}
-
-void tst_qquickxmllistmodel::noKeysValueChanges()
-{
- // The 'key' roles are 'name' and 'age', as defined in roleKeys.qml.
- // If a 'sport' value is changed, the model should not be reloaded,
- // since 'sport' is not marked as a key.
-
- QQmlComponent component(&engine, testFileUrl("roleKeys.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
-
- QString xml;
-
- xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
- model->setProperty("xml",xml);
- QTRY_COMPARE(model->rowCount(), 2);
-
- model->setProperty("xml","");
-
- QSignalSpy spyInsert(model, SIGNAL(rowsInserted(QModelIndex,int,int)));
- QSignalSpy spyRemove(model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
- QSignalSpy spyCount(model, SIGNAL(countChanged()));
-
- xml = makeItemXmlAndData("name=A,age=25,sport=AussieRules;name=B,age=35,sport=Athletics");
- model->setProperty("xml",xml);
-
- QList<int> roles = model->roleNames().keys();
- std::sort(roles.begin(), roles.end());
- // wait for the new xml data to be set, and verify no signals were emitted
- QTRY_VERIFY(model->data(model->index(0, 0), roles.at(2)).toString() != QLatin1String("Football"));
- QCOMPARE(model->data(model->index(0, 0), roles.at(2)).toString(), QLatin1String("AussieRules"));
-
- QCOMPARE(spyInsert.count(), 0);
- QCOMPARE(spyRemove.count(), 0);
- QCOMPARE(spyCount.count(), 0);
-
- QCOMPARE(model->rowCount(), 2);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::keysChanged()
-{
- // If the key roles change, the next time the data is reloaded, it should
- // delete all its data and build a clean model (i.e. same behaviour as
- // if no keys are set).
-
- QQmlComponent component(&engine, testFileUrl("roleKeys.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
-
- QString xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
- model->setProperty("xml",xml);
- QTRY_COMPARE(model->rowCount(), 2);
-
- model->setProperty("xml","");
-
- QSignalSpy spyInsert(model, SIGNAL(rowsInserted(QModelIndex,int,int)));
- QSignalSpy spyRemove(model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
- QSignalSpy spyCount(model, SIGNAL(countChanged()));
-
- QVERIFY(QMetaObject::invokeMethod(model, "disableNameKey"));
- model->setProperty("xml",xml);
-
- QTRY_VERIFY(spyInsert.count() > 0 && spyRemove.count() > 0);
-
- QCOMPARE(spyInsert.count(), 1);
- QCOMPARE(spyInsert[0][1].toInt(), 0);
- QCOMPARE(spyInsert[0][2].toInt(), 1);
-
- QCOMPARE(spyRemove.count(), 1);
- QCOMPARE(spyRemove[0][1].toInt(), 0);
- QCOMPARE(spyRemove[0][2].toInt(), 1);
-
- QCOMPARE(spyCount.count(), 0);
-
- delete model;
-}
-
-void tst_qquickxmllistmodel::threading()
-{
- QFETCH(int, xmlDataCount);
-
- QQmlComponent component(&engine, testFileUrl("roleKeys.qml"));
-
- QAbstractItemModel *m1 = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(m1 != 0);
- QAbstractItemModel *m2 = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(m2 != 0);
- QAbstractItemModel *m3 = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(m3 != 0);
-
- for (int dataCount=0; dataCount<xmlDataCount; dataCount++) {
-
- QString data1, data2, data3;
- for (int i=0; i<dataCount; i++) {
- data1 += "name=A" + QString::number(i) + ",age=1" + QString::number(i) + ",sport=Football;";
- data2 += "name=B" + QString::number(i) + ",age=2" + QString::number(i) + ",sport=Athletics;";
- data3 += "name=C" + QString::number(i) + ",age=3" + QString::number(i) + ",sport=Curling;";
- }
-
- //Set the xml data multiple times with randomized order and mixed with multiple event loops
- //to test the xml query reloading/aborting, the result should be stable.
- m1->setProperty("xml",makeItemXmlAndData(data1));
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m3->setProperty("xml",makeItemXmlAndData(data3));
- QCoreApplication::processEvents();
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m1->setProperty("xml",makeItemXmlAndData(data1));
- m2->setProperty("xml",makeItemXmlAndData(data2));
- QCoreApplication::processEvents();
- m3->setProperty("xml",makeItemXmlAndData(data3));
- QCoreApplication::processEvents();
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m1->setProperty("xml",makeItemXmlAndData(data1));
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m3->setProperty("xml",makeItemXmlAndData(data3));
- QCoreApplication::processEvents();
- m2->setProperty("xml",makeItemXmlAndData(data2));
- m3->setProperty("xml",makeItemXmlAndData(data3));
- m3->setProperty("xml",makeItemXmlAndData(data3));
- QCoreApplication::processEvents();
-
- QTRY_VERIFY(m1->rowCount() == dataCount && m2->rowCount() == dataCount && m3->rowCount() == dataCount);
-
- for (int i=0; i<dataCount; i++) {
- QModelIndex index = m1->index(i, 0);
- QList<int> roles = m1->roleNames().keys();
- std::sort(roles.begin(), roles.end());
- QCOMPARE(m1->data(index, roles.at(0)).toString(), QLatin1Char('A') + QString::number(i));
- QCOMPARE(m1->data(index, roles.at(1)).toString(), QLatin1Char('1') + QString::number(i));
- QCOMPARE(m1->data(index, roles.at(2)).toString(), QString("Football"));
-
- index = m2->index(i, 0);
- roles = m2->roleNames().keys();
- std::sort(roles.begin(), roles.end());
- QCOMPARE(m2->data(index, roles.at(0)).toString(), QLatin1Char('B') + QString::number(i));
- QCOMPARE(m2->data(index, roles.at(1)).toString(), QLatin1Char('2') + QString::number(i));
- QCOMPARE(m2->data(index, roles.at(2)).toString(), QString("Athletics"));
-
- index = m3->index(i, 0);
- roles = m3->roleNames().keys();
- std::sort(roles.begin(), roles.end());
- QCOMPARE(m3->data(index, roles.at(0)).toString(), QLatin1Char('C') + QString::number(i));
- QCOMPARE(m3->data(index, roles.at(1)).toString(), QLatin1Char('3') + QString::number(i));
- QCOMPARE(m3->data(index, roles.at(2)).toString(), QString("Curling"));
- }
- }
-
- delete m1;
- delete m2;
- delete m3;
-}
-
-void tst_qquickxmllistmodel::threading_data()
-{
- QTest::addColumn<int>("xmlDataCount");
-
- QTest::newRow("1") << 1;
- QTest::newRow("2") << 2;
- QTest::newRow("10") << 10;
-}
-
-void tst_qquickxmllistmodel::propertyChanges()
-{
- QQmlComponent component(&engine, testFileUrl("propertychanges.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel*>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 9);
-
- QObject *role = model->findChild<QObject*>("role");
- QVERIFY(role);
-
- QSignalSpy nameSpy(role, SIGNAL(nameChanged()));
- QSignalSpy querySpy(role, SIGNAL(queryChanged()));
- QSignalSpy isKeySpy(role, SIGNAL(isKeyChanged()));
-
- role->setProperty("name","size");
- role->setProperty("query","size/string()");
- role->setProperty("isKey",true);
-
- QCOMPARE(role->property("name").toString(), QString("size"));
- QCOMPARE(role->property("query").toString(), QString("size/string()"));
- QVERIFY(role->property("isKey").toBool());
-
- QCOMPARE(nameSpy.count(),1);
- QCOMPARE(querySpy.count(),1);
- QCOMPARE(isKeySpy.count(),1);
-
- role->setProperty("name","size");
- role->setProperty("query","size/string()");
- role->setProperty("isKey",true);
-
- QCOMPARE(nameSpy.count(),1);
- QCOMPARE(querySpy.count(),1);
- QCOMPARE(isKeySpy.count(),1);
-
- QSignalSpy sourceSpy(model, SIGNAL(sourceChanged()));
- QSignalSpy xmlSpy(model, SIGNAL(xmlChanged()));
- QSignalSpy modelQuerySpy(model, SIGNAL(queryChanged()));
- QSignalSpy namespaceDeclarationsSpy(model, SIGNAL(namespaceDeclarationsChanged()));
-
- model->setProperty("source",QUrl(""));
- model->setProperty("xml","<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>");
- model->setProperty("query","/Pets");
- model->setProperty("namespaceDeclarations","declare namespace media=\"http://search.yahoo.com/mrss/\";");
-
- QCOMPARE(model->property("source").toUrl(), QUrl(""));
- QCOMPARE(model->property("xml").toString(), QString("<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>"));
- QCOMPARE(model->property("query").toString(), QString("/Pets"));
- QCOMPARE(model->property("namespaceDeclarations").toString(), QString("declare namespace media=\"http://search.yahoo.com/mrss/\";"));
-
- QTRY_COMPARE(model->rowCount(), 1);
-
- QCOMPARE(sourceSpy.count(),1);
- QCOMPARE(xmlSpy.count(),1);
- QCOMPARE(modelQuerySpy.count(),1);
- QCOMPARE(namespaceDeclarationsSpy.count(),1);
-
- model->setProperty("source",QUrl(""));
- model->setProperty("xml","<Pets><Pet><name>Polly</name><type>Parrot</type><age>12</age><size>Small</size></Pet></Pets>");
- model->setProperty("query","/Pets");
- model->setProperty("namespaceDeclarations","declare namespace media=\"http://search.yahoo.com/mrss/\";");
-
- QCOMPARE(sourceSpy.count(),1);
- QCOMPARE(xmlSpy.count(),1);
- QCOMPARE(modelQuerySpy.count(),1);
- QCOMPARE(namespaceDeclarationsSpy.count(),1);
-
- QTRY_COMPARE(model->rowCount(), 1);
- delete model;
-}
-
-void tst_qquickxmllistmodel::selectAncestor()
-{
- QQmlComponent component(&engine, testFileUrl("groups.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- QTRY_COMPARE(model->rowCount(), 1);
-
- QModelIndex index = model->index(0, 0);
- QCOMPARE(model->data(index, Qt::UserRole).toInt(), 12);
- QCOMPARE(model->data(index, Qt::UserRole+1).toString(), QLatin1String("cats"));
-}
-
-void tst_qquickxmllistmodel::roleCrash()
-{
- // don't crash
- QQmlComponent component(&engine, testFileUrl("roleCrash.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- delete model;
-}
-
-class SortFilterProxyModel : public QSortFilterProxyModel
-{
- Q_OBJECT
- Q_PROPERTY(QObject *source READ source WRITE setSource)
-
-public:
- SortFilterProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) { sort(0); }
- QObject *source() const { return sourceModel(); }
- void setSource(QObject *source) { setSourceModel(qobject_cast<QAbstractItemModel *>(source)); }
-};
-
-void tst_qquickxmllistmodel::proxyCrash()
-{
- qmlRegisterType<SortFilterProxyModel>("SortFilterProxyModel", 1, 0, "SortFilterProxyModel");
-
- // don't crash
- QQmlComponent component(&engine, testFileUrl("proxyCrash.qml"));
- QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create());
- QVERIFY(model != 0);
- delete model;
-}
-
-QTEST_MAIN(tst_qquickxmllistmodel)
-
-#include "tst_qquickxmllistmodel.moc"
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 2ff606488c..7257a99d2a 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -25,6 +25,7 @@ qtConfig(opengl(es1|es2)?) {
PRIVATETESTS += \
nokeywords \
+ propertyrequirements \
qquickanimations \
qquickapplication \
qquickbehaviors \
@@ -40,13 +41,10 @@ PRIVATETESTS += \
qquickstyledtext \
qquickstates \
qquicksystempalette \
- qquicktimeline \
- qquickxmllistmodel
+ qquicktimeline
-# This test requires the xmlpatterns module
-!qtHaveModule(xmlpatterns): PRIVATETESTS -= qquickxmllistmodel
-
-QUICKTESTS = \
+QUICKTESTS += \
+ pointerhandlers \
qquickaccessible \
qquickanchors \
qquickanimatedimage \
@@ -65,6 +63,7 @@ QUICKTESTS = \
qquickitem2 \
qquickitemlayer \
qquicklistview \
+ qquicktableview \
qquickloader \
qquickmousearea \
qquickmultipointtoucharea \
@@ -91,6 +90,9 @@ QUICKTESTS = \
SUBDIRS += $$PUBLICTESTS
+# Following tests are too slow on qemu + software backend
+boot2qt: QUICKTESTS -= qquickgridview qquicklistview qquicktableview qquickpositioners
+
!qtConfig(accessibility):QUICKTESTS -= qquickaccessible
qtConfig(private_tests) {
diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp
index e0fe2c42fc..0e06ee6f50 100644
--- a/tests/auto/quick/rendernode/tst_rendernode.cpp
+++ b/tests/auto/quick/rendernode/tst_rendernode.cpp
@@ -120,7 +120,7 @@ private:
class MessUpNode : public QSGRenderNode, protected QOpenGLFunctions
{
public:
- MessUpNode() : initialized(false) { }
+ MessUpNode() {}
StateFlags changedStates() const override
{
@@ -157,7 +157,7 @@ public:
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}
- bool initialized;
+ bool initialized = false;
};
class MessUpItem : public QQuickItem
@@ -213,6 +213,11 @@ void tst_rendernode::renderOrder()
{
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("RenderOrder.qml");
const qreal scaleFactor = QGuiApplication::primaryScreen()->devicePixelRatio();
@@ -237,6 +242,11 @@ void tst_rendernode::messUpState()
{
if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("This test does not work at display depths < 24");
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QImage fb = runTest("MessUpState.qml");
int x1 = 0;
int x2 = fb.width() / 2;
@@ -290,6 +300,10 @@ public:
void tst_rendernode::matrix()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
qmlRegisterType<StateRecordingRenderNodeItem>("RenderNode", 1, 0, "StateRecorder");
StateRecordingRenderNode::matrices.clear();
runTest("matrix.qml");
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 2cd3a041c8..063358c795 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -47,6 +47,9 @@
#include "../../shared/util.h"
#include "../shared/visualtestutil.h"
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+
using namespace QQuickVisualTestUtil;
class PerPixelRect : public QQuickItem
@@ -113,7 +116,8 @@ private slots:
private:
bool m_brokenMipmapSupport;
- QQuickView *createView(const QString &file, QWindow *parent = 0, int x = -1, int y = -1, int w = -1, int h = -1);
+ QQuickView *createView(const QString &file, QWindow *parent = nullptr, int x = -1, int y = -1, int w = -1, int h = -1);
+ bool isRunningOnOpenGL();
};
template <typename T> class ScopedList : public QList<T> {
@@ -131,38 +135,40 @@ void tst_SceneGraph::initTestCase()
qDebug() << "RenderLoop: " << loop;
#if QT_CONFIG(opengl)
- QOpenGLContext context;
- context.setFormat(loop->sceneGraphContext()->defaultSurfaceFormat());
- context.create();
- QSurfaceFormat format = context.format();
-
- QOffscreenSurface surface;
- surface.setFormat(format);
- surface.create();
- if (!context.makeCurrent(&surface))
- qFatal("Failed to create a GL context...");
-
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- qDebug() << "R/G/B/A Buffers: " << format.redBufferSize() << format.greenBufferSize() << format.blueBufferSize() << format.alphaBufferSize();
- qDebug() << "Depth Buffer: " << format.depthBufferSize();
- qDebug() << "Stencil Buffer: " << format.stencilBufferSize();
- qDebug() << "Samples: " << format.samples();
- int textureSize;
- funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &textureSize);
- qDebug() << "Max Texture Size: " << textureSize;
- qDebug() << "GL_VENDOR: " << (const char *) funcs->glGetString(GL_VENDOR);
- qDebug() << "GL_RENDERER: " << (const char *) funcs->glGetString(GL_RENDERER);
- QByteArray version = (const char *) funcs->glGetString(GL_VERSION);
- qDebug() << "GL_VERSION: " << version.constData();
- QSet<QByteArray> exts = context.extensions();
- QByteArray all;
- foreach (const QByteArray &e, exts) all += ' ' + e;
- qDebug() << "GL_EXTENSIONS: " << all.constData();
-
- m_brokenMipmapSupport = version.contains("Mesa 10.1") || version.contains("Mesa 9.");
- qDebug() << "Broken Mipmap: " << m_brokenMipmapSupport;
-
- context.doneCurrent();
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
+ QOpenGLContext context;
+ context.setFormat(loop->sceneGraphContext()->defaultSurfaceFormat());
+ context.create();
+ QSurfaceFormat format = context.format();
+
+ QOffscreenSurface surface;
+ surface.setFormat(format);
+ surface.create();
+ if (!context.makeCurrent(&surface))
+ qFatal("Failed to create a GL context...");
+
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ qDebug() << "R/G/B/A Buffers: " << format.redBufferSize() << format.greenBufferSize() << format.blueBufferSize() << format.alphaBufferSize();
+ qDebug() << "Depth Buffer: " << format.depthBufferSize();
+ qDebug() << "Stencil Buffer: " << format.stencilBufferSize();
+ qDebug() << "Samples: " << format.samples();
+ int textureSize;
+ funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &textureSize);
+ qDebug() << "Max Texture Size: " << textureSize;
+ qDebug() << "GL_VENDOR: " << (const char *) funcs->glGetString(GL_VENDOR);
+ qDebug() << "GL_RENDERER: " << (const char *) funcs->glGetString(GL_RENDERER);
+ QByteArray version = (const char *) funcs->glGetString(GL_VERSION);
+ qDebug() << "GL_VERSION: " << version.constData();
+ QSet<QByteArray> exts = context.extensions();
+ QByteArray all;
+ foreach (const QByteArray &e, exts) all += ' ' + e;
+ qDebug() << "GL_EXTENSIONS: " << all.constData();
+
+ m_brokenMipmapSupport = version.contains("Mesa 10.1") || version.contains("Mesa 9.");
+ qDebug() << "Broken Mipmap: " << m_brokenMipmapSupport;
+
+ context.doneCurrent();
+ }
#endif
}
@@ -225,12 +231,16 @@ void tst_SceneGraph::manyWindows_data()
#if QT_CONFIG(opengl)
struct ShareContextResetter {
public:
- ~ShareContextResetter() { qt_gl_set_global_share_context(0); }
+ ~ShareContextResetter() { qt_gl_set_global_share_context(nullptr); }
};
#endif
void tst_SceneGraph::manyWindows()
{
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+
QFETCH(QString, file);
QFETCH(bool, toplevel);
QFETCH(bool, shared);
@@ -254,27 +264,30 @@ void tst_SceneGraph::manyWindows()
const int COUNT = 4;
QImage baseLine;
+ QString errorMessage;
for (int i=0; i<COUNT; ++i) {
views << createView(file, parent.data(), (i % 2) * 100, (i / 2) * 100, 100, 100);
}
for (int i=0; i<COUNT; ++i) {
QQuickView *view = views.at(i);
- QTest::qWaitForWindowExposed(view);
+ QVERIFY(QTest::qWaitForWindowExposed(view));
QImage content = view->grabWindow();
if (i == 0) {
baseLine = content;
QVERIFY(containsSomethingOtherThanWhite(baseLine));
} else {
- QVERIFY(compareImages(content, baseLine));
+ QVERIFY2(compareImages(content, baseLine, &errorMessage),
+ qPrintable(errorMessage));
}
}
// Wipe and recreate one (scope pointer delets it...)
delete views.takeLast();
QQuickView *last = createView(file, parent.data(), 100, 100, 100, 100);
- QTest::qWaitForWindowExposed(last);
+ QVERIFY(QTest::qWaitForWindowExposed(last));
views << last;
- QVERIFY(compareImages(baseLine, last->grabWindow()));
+ QVERIFY2(compareImages(baseLine, last->grabWindow(), &errorMessage),
+ qPrintable(errorMessage));
// Wipe and recreate all
qDeleteAll(views);
@@ -285,9 +298,10 @@ void tst_SceneGraph::manyWindows()
}
for (int i=0; i<COUNT; ++i) {
QQuickView *view = views.at(i);
- QTest::qWaitForWindowExposed(view);
+ QVERIFY(QTest::qWaitForWindowExposed(view));
QImage content = view->grabWindow();
- QVERIFY(compareImages(content, baseLine));
+ QVERIFY2(compareImages(content, baseLine, &errorMessage),
+ qPrintable(errorMessage));
}
}
@@ -430,12 +444,8 @@ void tst_SceneGraph::render_data()
void tst_SceneGraph::render()
{
- QQuickView dummy;
- dummy.show();
- QTest::qWaitForWindowExposed(&dummy);
- if (dummy.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL)
+ if (!isRunningOnOpenGL())
QSKIP("Skipping complex rendering tests due to not running with OpenGL");
- dummy.hide();
QFETCH(QString, file);
QFETCH(QList<Sample>, baseStage);
@@ -485,6 +495,9 @@ void tst_SceneGraph::render()
// current on the other window.
void tst_SceneGraph::hideWithOtherContext()
{
+ if (!isRunningOnOpenGL())
+ QSKIP("Skipping OpenGL context test due to not running with OpenGL");
+
QWindow window;
window.setSurfaceType(QWindow::OpenGLSurface);
window.resize(100, 100);
@@ -500,9 +513,6 @@ void tst_SceneGraph::hideWithOtherContext()
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
- if (view.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL)
- QSKIP("Skipping OpenGL context test due to not running with OpenGL");
-
renderingOnMainThread = view.openglContext()->thread() == QGuiApplication::instance()->thread();
// Make the local context current on the local window...
@@ -542,13 +552,24 @@ void tst_SceneGraph::createTextureFromImage()
QQuickView view;
view.show();
- QTest::qWaitForWindowExposed(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QTRY_VERIFY(view.isSceneGraphInitialized());
QScopedPointer<QSGTexture> texture(view.createTextureFromImage(image, (QQuickWindow::CreateTextureOptions) flags));
QCOMPARE(texture->hasAlphaChannel(), expectedAlpha);
}
+bool tst_SceneGraph::isRunningOnOpenGL()
+{
+ bool retval = false;
+ QQuickView dummy;
+ dummy.show();
+ QTest::qWaitForWindowExposed(&dummy);
+ if (dummy.rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL)
+ retval = true;
+ dummy.hide();
+ return retval;
+}
#include "tst_scenegraph.moc"
diff --git a/tests/auto/quick/shared/geometrytestutil.cpp b/tests/auto/quick/shared/geometrytestutil.cpp
new file mode 100644
index 0000000000..07a755e9a5
--- /dev/null
+++ b/tests/auto/quick/shared/geometrytestutil.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geometrytestutil.h"
+
+#include <QQuickItem>
+
+QSizeChangeListener::QSizeChangeListener(QQuickItem *item) :
+ item(item)
+{
+ connect(item, &QQuickItem::widthChanged, this, &QSizeChangeListener::onSizeChanged);
+ connect(item, &QQuickItem::heightChanged, this, &QSizeChangeListener::onSizeChanged);
+}
+
+void QSizeChangeListener::onSizeChanged()
+{
+ append(QSize(item->width(), item->height()));
+}
diff --git a/tests/auto/quick/shared/geometrytestutil.h b/tests/auto/quick/shared/geometrytestutil.h
new file mode 100644
index 0000000000..2cf19ed7ff
--- /dev/null
+++ b/tests/auto/quick/shared/geometrytestutil.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKGEOMETRYTESTUTIL_H
+#define QQUICKGEOMETRYTESTUTIL_H
+
+#include <QObject>
+#include <QVector>
+#include <QSize>
+
+QT_FORWARD_DECLARE_CLASS(QQuickItem)
+
+class QSizeChangeListener : public QObject, public QVector<QSize>
+{
+ Q_OBJECT
+public:
+ explicit QSizeChangeListener(QQuickItem *item);
+private slots:
+ void onSizeChanged();
+private:
+ QQuickItem *item;
+};
+
+#endif // QQUICKGEOMETRYTESTUTIL_H
diff --git a/tests/auto/quick/shared/util.pri b/tests/auto/quick/shared/util.pri
index bd2d202f1d..359c312328 100644
--- a/tests/auto/quick/shared/util.pri
+++ b/tests/auto/quick/shared/util.pri
@@ -2,8 +2,10 @@
QT += core-private gui-private qml-private quick-private
HEADERS += $$PWD/visualtestutil.h \
+ $$PWD/geometrytestutil.h \
$$PWD/viewtestutil.h
SOURCES += $$PWD/visualtestutil.cpp \
+ $$PWD/geometrytestutil.cpp \
$$PWD/viewtestutil.cpp
DEFINES += QT_QMLTEST_DATADIR=\\\"$${_PRO_FILE_PWD_}/data\\\"
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index cb2b8be97a..5631ffe047 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -28,6 +28,7 @@
#include "viewtestutil.h"
+#include <QtCore/QRandomGenerator>
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickView>
#include <QtGui/QScreen>
@@ -37,6 +38,7 @@
#include <private/qquickwindow_p.h>
#include <private/qquickitemview_p_p.h>
+QT_BEGIN_NAMESPACE
QQuickView *QQuickViewTestUtil::createView()
{
@@ -152,6 +154,12 @@ int QQuickViewTestUtil::QaimModel::rowCount(const QModelIndex &parent) const
return list.count();
}
+int QQuickViewTestUtil::QaimModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return columns;
+}
+
QHash<int,QByteArray> QQuickViewTestUtil::QaimModel::roleNames() const
{
QHash<int,QByteArray> roles = QAbstractListModel::roleNames();
@@ -173,7 +181,7 @@ QVariant QQuickViewTestUtil::QaimModel::data(const QModelIndex &index, int role)
int QQuickViewTestUtil::QaimModel::count() const
{
- return rowCount();
+ return rowCount() * columnCount();
}
QString QQuickViewTestUtil::QaimModel::name(int index) const
@@ -356,7 +364,6 @@ QQuickViewTestUtil::StressTestModel::StressTestModel()
t->setInterval(500);
t->start();
- qsrand(qHash(QDateTime::currentDateTime()));
connect(t, &QTimer::timeout, this, &StressTestModel::updateModel);
}
@@ -374,7 +381,7 @@ void QQuickViewTestUtil::StressTestModel::updateModel()
{
if (m_rowCount > 10) {
for (int i = 0; i < 10; ++i) {
- int rnum = qrand() % m_rowCount;
+ int rnum = QRandomGenerator::global()->bounded(m_rowCount);
beginRemoveRows(QModelIndex(), rnum, rnum);
m_rowCount--;
endRemoveRows();
@@ -382,7 +389,7 @@ void QQuickViewTestUtil::StressTestModel::updateModel()
}
if (m_rowCount < 20) {
for (int i = 0; i < 10; ++i) {
- int rnum = qrand() % m_rowCount;
+ int rnum = QRandomGenerator::global()->bounded(m_rowCount);
beginInsertRows(QModelIndex(), rnum, rnum);
m_rowCount++;
endInsertRows();
@@ -398,7 +405,7 @@ bool QQuickViewTestUtil::testVisibleItems(const QQuickItemViewPrivate *priv, boo
for (int i = 0; i < priv->visibleItems.count(); ++i) {
FxViewItem *item = priv->visibleItems.at(i);
if (!item) {
- *failItem = Q_NULLPTR;
+ *failItem = nullptr;
return false;
}
#if 0
@@ -445,3 +452,32 @@ namespace QQuickTouchUtils {
}
}
+
+namespace QQuickTest {
+ // Initialize view, set Url, center in available geometry, move mouse away if desired
+ bool initView(QQuickView &v, const QUrl &url, bool moveMouseOut, QByteArray *errorMessage)
+ {
+ v.setBaseSize(QSize(240,320));
+ v.setSource(url);
+ while (v.status() == QQuickView::Loading)
+ QTest::qWait(10);
+ if (v.status() != QQuickView::Ready) {
+ foreach (const QQmlError &e, v.errors())
+ errorMessage->append(e.toString().toLocal8Bit() + '\n');
+ return false;
+ }
+ const QRect screenGeometry = v.screen()->availableGeometry();
+ const QSize size = v.size();
+ const QPoint offset = QPoint(size.width() / 2, size.height() / 2);
+ v.setFramePosition(screenGeometry.center() - offset);
+ #if QT_CONFIG(cursor) // Get the cursor out of the way.
+ if (moveMouseOut)
+ QCursor::setPos(v.geometry().topRight() + QPoint(100, 100));
+ #else
+ Q_UNUSED(moveMouseOut)
+ #endif
+ return true;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/quick/shared/viewtestutil.h b/tests/auto/quick/shared/viewtestutil.h
index b11d5e4859..5e725fdf11 100644
--- a/tests/auto/quick/shared/viewtestutil.h
+++ b/tests/auto/quick/shared/viewtestutil.h
@@ -37,6 +37,8 @@ QT_FORWARD_DECLARE_CLASS(QQuickView)
QT_FORWARD_DECLARE_CLASS(QQuickItemViewPrivate)
QT_FORWARD_DECLARE_CLASS(FxViewItem)
+QT_BEGIN_NAMESPACE
+
namespace QQuickViewTestUtil
{
QQuickView *createView();
@@ -76,6 +78,7 @@ namespace QQuickViewTestUtil
QaimModel(QObject *parent=0);
int rowCount(const QModelIndex &parent=QModelIndex()) const;
+ int columnCount(const QModelIndex &parent=QModelIndex()) const;
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
QHash<int,QByteArray> roleNames() const;
@@ -104,6 +107,8 @@ namespace QQuickViewTestUtil
using QAbstractListModel::dataChanged;
+ int columns = 1;
+
private:
QList<QPair<QString,QString> > list;
};
@@ -182,6 +187,12 @@ namespace QQuickTouchUtils {
void flush(QQuickWindow *window);
}
+namespace QQuickTest {
+ bool initView(QQuickView &v, const QUrl &url, bool moveMouseOut, QByteArray *errorMessage);
+}
+
+QT_END_NAMESPACE
+
Q_DECLARE_METATYPE(QQuickViewTestUtil::QaimModel*)
Q_DECLARE_METATYPE(QQuickViewTestUtil::ListChange)
Q_DECLARE_METATYPE(QList<QQuickViewTestUtil::ListChange>)
diff --git a/tests/auto/quick/shared/visualtestutil.cpp b/tests/auto/quick/shared/visualtestutil.cpp
index eabfe5368b..de2cf2bd5b 100644
--- a/tests/auto/quick/shared/visualtestutil.cpp
+++ b/tests/auto/quick/shared/visualtestutil.cpp
@@ -66,12 +66,18 @@ void QQuickVisualTestUtil::dumpTree(QQuickItem *parent, int depth)
// distance field glyph pixels have a measurable, but not visible
// pixel error. This was GT-216 with the ubuntu "nvidia-319" driver package.
// llvmpipe does not show the same issue.
-bool QQuickVisualTestUtil::compareImages(const QImage &ia, const QImage &ib)
+
+bool QQuickVisualTestUtil::compareImages(const QImage &ia, const QImage &ib, QString *errorMessage)
{
- if (ia.size() != ib.size())
- qDebug() << "images are of different size" << ia.size() << ib.size();
- Q_ASSERT(ia.size() == ib.size());
- Q_ASSERT(ia.format() == ib.format());
+ if (ia.size() != ib.size()) {
+ QDebug(errorMessage) << "Images are of different size:" << ia.size() << ib.size()
+ << "DPR:" << ia.devicePixelRatio() << ib.devicePixelRatio();
+ return false;
+ }
+ if (ia.format() != ib.format()) {
+ QDebug(errorMessage) << "Images are of different formats:" << ia.format() << ib.format();
+ return false;
+ }
int w = ia.width();
int h = ia.height();
@@ -84,14 +90,14 @@ bool QQuickVisualTestUtil::compareImages(const QImage &ia, const QImage &ib)
uint b = bs[x];
// No tolerance for error in the alpha.
- if ((a & 0xff000000) != (b & 0xff000000))
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
- return false;
- if (qAbs(qRed(a) - qRed(b)) > tolerance)
+ if ((a & 0xff000000) != (b & 0xff000000)
+ || qAbs(qRed(a) - qRed(b)) > tolerance
+ || qAbs(qRed(a) - qRed(b)) > tolerance
+ || qAbs(qRed(a) - qRed(b)) > tolerance) {
+ QDebug(errorMessage) << "Mismatch at:" << x << y << ':'
+ << hex << showbase << a << b;
return false;
+ }
}
}
return true;
diff --git a/tests/auto/quick/shared/visualtestutil.h b/tests/auto/quick/shared/visualtestutil.h
index 2daf86cd83..e623e3e225 100644
--- a/tests/auto/quick/shared/visualtestutil.h
+++ b/tests/auto/quick/shared/visualtestutil.h
@@ -97,10 +97,7 @@ namespace QQuickVisualTestUtil
return items;
}
- bool compareImages(const QImage &ia, const QImage &ib);
+ bool compareImages(const QImage &ia, const QImage &ib, QString *errorMessage);
}
-#define QQUICK_VERIFY_POLISH(item) \
- QTRY_COMPARE(QQuickItemPrivate::get(item)->polishScheduled, false)
-
#endif // QQUICKVISUALTESTUTIL_H
diff --git a/tests/auto/quick/sharedimage/tst_sharedimage.cpp b/tests/auto/quick/sharedimage/tst_sharedimage.cpp
index b91fc8a0de..afadb76ad0 100644
--- a/tests/auto/quick/sharedimage/tst_sharedimage.cpp
+++ b/tests/auto/quick/sharedimage/tst_sharedimage.cpp
@@ -90,7 +90,7 @@ void tst_sharedimage::compareToPlainLoad()
engine.loadData(i ? sharedScript : plainScript);
QVERIFY(engine.rootObjects().size());
QQuickImage *obj = qobject_cast<QQuickImage*>(engine.rootObjects().at(0));
- QVERIFY(obj != 0);
+ QVERIFY(obj != nullptr);
QTRY_VERIFY(!obj->image().isNull());
images[i] = obj->image();
}
diff --git a/tests/auto/quick/touchmouse/BLACKLIST b/tests/auto/quick/touchmouse/BLACKLIST
new file mode 100644
index 0000000000..b2ba52eca9
--- /dev/null
+++ b/tests/auto/quick/touchmouse/BLACKLIST
@@ -0,0 +1,2 @@
+[buttonOnDelayedPressFlickable]
+windows gcc developer-build
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index 39f2961927..7fccb895db 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -28,8 +28,10 @@
#include <QtTest/QtTest>
+#include <QDebug>
#include <QtGui/qstylehints.h>
+#include <private/qdebug_p.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
@@ -46,6 +48,8 @@
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
struct Event
{
Event(QEvent::Type t, QPoint mouse, QPoint global)
@@ -62,6 +66,21 @@ struct Event
QList<QTouchEvent::TouchPoint> points;
};
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const struct Event &event) {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ dbg << "Event(";
+ QtDebugUtils::formatQEnum(dbg, event.type);
+ if (event.points.isEmpty())
+ dbg << " @ " << event.mousePos << " global " << event.mousePosGlobal;
+ else
+ dbg << ", " << event.points.count() << " touchpoints: " << event.points;
+ dbg << ')';
+ return dbg;
+}
+#endif
+
class EventItem : public QQuickItem
{
Q_OBJECT
@@ -70,10 +89,13 @@ Q_SIGNALS:
void onTouchEvent(QQuickItem *receiver);
public:
- EventItem(QQuickItem *parent = 0)
- : QQuickItem(parent), touchUngrabCount(0), acceptMouse(false), acceptTouch(false), filterTouch(false), point0(-1)
+ EventItem(QQuickItem *parent = nullptr)
+ : QQuickItem(parent)
{
setAcceptedMouseButtons(Qt::LeftButton);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ setAcceptTouchEvents(true);
+#endif
}
void touchEvent(QTouchEvent *event)
@@ -121,10 +143,10 @@ public:
}
QList<Event> eventList;
- int touchUngrabCount;
- bool acceptMouse;
- bool acceptTouch;
- bool filterTouch; // when used as event filter
+ int touchUngrabCount = 0;
+ bool acceptMouse = false;
+ bool acceptTouch = false;
+ bool filterTouch = false; // when used as event filter
bool eventFilter(QObject *, QEvent *event)
{
@@ -143,7 +165,7 @@ public:
}
return false;
}
- int point0;
+ int point0 = -1;
};
class tst_TouchMouse : public QQmlDataTest
@@ -157,6 +179,7 @@ public:
private slots:
void initTestCase();
+ void simpleTouchEvent_data();
void simpleTouchEvent();
void testEventFilter();
void mouse();
@@ -201,27 +224,34 @@ private:
QQuickView *tst_TouchMouse::createView()
{
- QQuickView *window = new QQuickView(0);
+ QQuickView *window = new QQuickView(nullptr);
return window;
}
void tst_TouchMouse::initTestCase()
{
- // This test assumes that we don't get synthesized mouse events from QGuiApplication
- qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
-
QQmlDataTest::initTestCase();
qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem");
}
+void tst_TouchMouse::simpleTouchEvent_data()
+{
+ QTest::addColumn<bool>("synthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents
+ QTest::newRow("no synth") << false;
+ QTest::newRow("synth") << true;
+}
+
void tst_TouchMouse::simpleTouchEvent()
{
+ QFETCH(bool, synthMouse);
+ qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, synthMouse);
+
QScopedPointer<QQuickView> window(createView());
window->setSource(testFileUrl("singleitem.qml"));
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
QVERIFY(eventItem1);
@@ -232,16 +262,16 @@ void tst_TouchMouse::simpleTouchEvent()
QTest::touchEvent(window.data(), device).press(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
// Get a touch and then mouse event offered
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
p1 += QPoint(10, 0);
QTest::touchEvent(window.data(), device).move(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
// Not accepted, no updates
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
QTest::touchEvent(window.data(), device).release(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
eventItem1->eventList.clear();
// Accept touch
@@ -269,10 +299,11 @@ void tst_TouchMouse::simpleTouchEvent()
p1 = QPoint(20, 20);
QTest::touchEvent(window.data(), device).press(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
- QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
- QCOMPARE(window->mouseGrabberItem(), eventItem1);
+ if (synthMouse)
+ QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
+ QCOMPARE(window->mouseGrabberItem(), synthMouse ? eventItem1 : nullptr);
QPoint localPos = eventItem1->mapFromScene(p1).toPoint();
QPoint globalPos = window->mapToGlobal(p1);
@@ -280,21 +311,31 @@ void tst_TouchMouse::simpleTouchEvent()
QCOMPARE(eventItem1->eventList.at(0).points.at(0).pos().toPoint(), localPos);
QCOMPARE(eventItem1->eventList.at(0).points.at(0).scenePos().toPoint(), scenePos);
QCOMPARE(eventItem1->eventList.at(0).points.at(0).screenPos().toPoint(), globalPos);
- QCOMPARE(eventItem1->eventList.at(1).mousePos, localPos);
- QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos);
+ if (synthMouse) {
+ QCOMPARE(eventItem1->eventList.at(1).mousePos, localPos);
+ QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos);
+ }
p1 += QPoint(10, 0);
QTest::touchEvent(window.data(), device).move(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
- QCOMPARE(eventItem1->eventList.size(), 4);
- QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
- QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 4 : 1);
+ if (synthMouse) {
+ QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
+ QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
+ }
+ // else, if there was no synth-mouse and we didn't accept the touch,
+ // TouchUpdate was not sent to eventItem1 either.
QTest::touchEvent(window.data(), device).release(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
- QCOMPARE(eventItem1->eventList.size(), 7);
- QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd);
- QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease);
- QCOMPARE(eventItem1->eventList.at(6).type, QEvent::UngrabMouse);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 7 : 1);
+ if (synthMouse) {
+ QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd);
+ QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease);
+ QCOMPARE(eventItem1->eventList.at(6).type, QEvent::UngrabMouse);
+ }
+ // else, if there was no synth-mouse and we didn't accept the touch,
+ // TouchEnd was not sent to eventItem1 either.
eventItem1->eventList.clear();
// wait to avoid getting a double click event
@@ -307,16 +348,17 @@ void tst_TouchMouse::simpleTouchEvent()
p1 = QPoint(20, 20);
QTest::touchEvent(window.data(), device).press(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
- QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
+ if (synthMouse)
+ QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
p1 += QPoint(10, 0);
QTest::touchEvent(window.data(), device).move(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
QTest::touchEvent(window.data(), device).release(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
- QCOMPARE(eventItem1->eventList.size(), 2);
+ QCOMPARE(eventItem1->eventList.size(), synthMouse ? 2 : 1);
eventItem1->eventList.clear();
// wait to avoid getting a double click event
@@ -383,7 +425,7 @@ void tst_TouchMouse::mouse()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
QVERIFY(eventItem1);
@@ -413,7 +455,7 @@ void tst_TouchMouse::touchOverMouse()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
QVERIFY(eventItem1);
@@ -453,7 +495,7 @@ void tst_TouchMouse::mouseOverTouch()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
QVERIFY(eventItem1);
@@ -494,7 +536,7 @@ void tst_TouchMouse::buttonOnFlickable()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
QVERIFY(flickable);
@@ -572,7 +614,7 @@ void tst_TouchMouse::buttonOnFlickable()
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
QVERIFY(windowPriv->touchMouseId != -1);
auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
- QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1);
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), eventItem1);
QCOMPARE(window->mouseGrabberItem(), eventItem1);
int dragDelta = -qApp->styleHints()->startDragDistance();
@@ -594,7 +636,7 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(window->mouseGrabberItem(), flickable);
QVERIFY(windowPriv->touchMouseId != -1);
- QCOMPARE(pointerEvent->point(0)->grabber(), flickable);
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), flickable);
QVERIFY(flickable->isMovingVertically());
QTest::touchEvent(window.data(), device).release(0, p3, window.data());
@@ -612,7 +654,7 @@ void tst_TouchMouse::touchButtonOnFlickable()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
QVERIFY(flickable);
@@ -633,7 +675,7 @@ void tst_TouchMouse::touchButtonOnFlickable()
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
QVERIFY(windowPriv->touchMouseId == -1);
auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
- QCOMPARE(pointerEvent->point(0)->grabber(), eventItem2);
+ QCOMPARE(pointerEvent->point(0)->grabberItem(), eventItem2);
QCOMPARE(window->mouseGrabberItem(), nullptr);
int dragDelta = qApp->styleHints()->startDragDistance() * -0.7;
@@ -649,12 +691,12 @@ void tst_TouchMouse::touchButtonOnFlickable()
QTest::touchEvent(window.data(), device).move(0, p3, window.data());
QQuickTouchUtils::flush(window.data());
+ QTRY_COMPARE(eventItem2->touchUngrabCount, 1);
QVERIFY(eventItem2->eventList.size() > 2);
QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
- QCOMPARE(eventItem2->touchUngrabCount, 1);
QCOMPARE(window->mouseGrabberItem(), flickable);
QVERIFY(windowPriv->touchMouseId != -1);
- QCOMPARE(pointerEvent->point(0)->grabber(), flickable);
+ QCOMPARE(pointerEvent->point(0)->grabberItem(), flickable);
QVERIFY(flickable->isMovingVertically());
QTest::touchEvent(window.data(), device).release(0, p3, window.data());
@@ -664,14 +706,18 @@ void tst_TouchMouse::touchButtonOnFlickable()
void tst_TouchMouse::buttonOnDelayedPressFlickable_data()
{
QTest::addColumn<bool>("scrollBeforeDelayIsOver");
+ QTest::addColumn<bool>("releaseBeforeDelayIsOver");
// the item should never see the event,
// due to the pressDelay which never delivers if we start moving
- QTest::newRow("scroll before press delay is over") << true;
+ QTest::newRow("scroll before press delay is over") << true << false;
+
+ // after release, the item should see the press and release via event replay (QTBUG-61144)
+ QTest::newRow("release before press delay is over") << false << true;
// wait until the "button" sees the press but then
// start moving: the button gets a press and cancel event
- QTest::newRow("scroll after press delay is over") << false;
+ QTest::newRow("scroll after press delay is over") << false << false;
}
void tst_TouchMouse::buttonOnDelayedPressFlickable()
@@ -680,6 +726,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
// - eventItem1 y: 100, height 100
// - eventItem2 y: 300, height 100
QFETCH(bool, scrollBeforeDelayIsOver);
+ QFETCH(bool, releaseBeforeDelayIsOver);
qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true);
filteredEventList.clear();
@@ -689,7 +736,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
QVERIFY(flickable);
@@ -718,11 +765,12 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
// touch press
QPoint p1 = QPoint(10, 110);
+ QPoint pEnd = p1;
QTest::touchEvent(window.data(), device).press(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
- if (scrollBeforeDelayIsOver) {
- // no events, the flickable got scrolled, the button sees nothing
+ if (scrollBeforeDelayIsOver || releaseBeforeDelayIsOver) {
+ // no events yet: press is delayed
QCOMPARE(eventItem1->eventList.size(), 0);
} else {
// wait until the button sees the press
@@ -731,45 +779,64 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
QCOMPARE(filteredEventList.count(), 1);
}
- p1 += QPoint(0, -10);
- QPoint p2 = p1 + QPoint(0, -10);
- QPoint p3 = p2 + QPoint(0, -10);
- QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).move(0, p1, window.data());
- QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).move(0, p2, window.data());
- QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).move(0, p3, window.data());
- QQuickTouchUtils::flush(window.data());
- QTRY_VERIFY(flickable->isMovingVertically());
+ if (!releaseBeforeDelayIsOver) {
+ // move the touchpoint: try to flick
+ p1 += QPoint(0, -10);
+ QPoint p2 = p1 + QPoint(0, -10);
+ pEnd = p2 + QPoint(0, -10);
+ QQuickTouchUtils::flush(window.data());
+ QTest::touchEvent(window.data(), device).move(0, p1, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QTest::touchEvent(window.data(), device).move(0, p2, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QTest::touchEvent(window.data(), device).move(0, pEnd, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QTRY_VERIFY(flickable->isMovingVertically());
+
+ if (scrollBeforeDelayIsOver) {
+ QCOMPARE(eventItem1->eventList.size(), 0);
+ QCOMPARE(filteredEventList.count(), 0);
+ } else {
+ // see at least press, move and ungrab
+ QTRY_VERIFY(eventItem1->eventList.size() > 2);
+ QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
+ QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse);
+ QCOMPARE(filteredEventList.count(), 1);
+ }
- if (scrollBeforeDelayIsOver) {
- QCOMPARE(eventItem1->eventList.size(), 0);
- QCOMPARE(filteredEventList.count(), 0);
- } else {
- // see at least press, move and ungrab
- QTRY_VERIFY(eventItem1->eventList.size() > 2);
- QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
- QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse);
- QCOMPARE(filteredEventList.count(), 1);
+ // flickable should have the mouse grab, and have moved the itemForTouchPointId
+ // for the touchMouseId to the new grabber.
+ QCOMPARE(window->mouseGrabberItem(), flickable);
+ QVERIFY(windowPriv->touchMouseId != -1);
+ auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
+ QCOMPARE(pointerEvent->point(0)->grabberItem(), flickable);
}
- // flickable should have the mouse grab, and have moved the itemForTouchPointId
- // for the touchMouseId to the new grabber.
- QCOMPARE(window->mouseGrabberItem(), flickable);
- QVERIFY(windowPriv->touchMouseId != -1);
- auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
- QCOMPARE(pointerEvent->point(0)->grabber(), flickable);
-
- QTest::touchEvent(window.data(), device).release(0, p3, window.data());
+ QTest::touchEvent(window.data(), device).release(0, pEnd, window.data());
QQuickTouchUtils::flush(window.data());
- // We should not have received any synthesised mouse events from Qt gui,
- // just the delayed press.
- if (scrollBeforeDelayIsOver)
- QCOMPARE(filteredEventList.count(), 0);
- else
- QCOMPARE(filteredEventList.count(), 1);
+ if (releaseBeforeDelayIsOver) {
+ // when the touchpoint was released, the child saw the delayed press and the release in sequence
+ qCDebug(lcTests) << "expected delivered events: press, release, ungrab" << eventItem1->eventList;
+ qCDebug(lcTests) << "expected filtered events: delayed press, release" << filteredEventList;
+ QTRY_COMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
+ QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease);
+ QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse);
+ // QQuickWindow filters the delayed press and release
+ QCOMPARE(filteredEventList.count(), 2);
+ QCOMPARE(filteredEventList.at(0).type, QEvent::MouseButtonPress);
+ QCOMPARE(filteredEventList.at(1).type, QEvent::MouseButtonRelease);
+ } else {
+ // QQuickWindow filters the delayed press if there was one; otherwise nothing
+ if (scrollBeforeDelayIsOver) {
+ QCOMPARE(filteredEventList.count(), 0);
+ } else {
+ qCDebug(lcTests) << "expected filtered event: delayed press" << filteredEventList;
+ QCOMPARE(filteredEventList.count(), 1);
+ QCOMPARE(filteredEventList.at(0).type, QEvent::MouseButtonPress);
+ }
+ }
}
void tst_TouchMouse::buttonOnTouch()
@@ -787,7 +854,7 @@ void tst_TouchMouse::buttonOnTouch()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
QVERIFY(pinchArea);
@@ -805,6 +872,7 @@ void tst_TouchMouse::buttonOnTouch()
EventItem *eventItem4 = window->rootObject()->findChild<EventItem*>("eventItem4");
QVERIFY(eventItem4);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window.data(), device, false);
// Test the common case of a mouse area on top of pinch
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
@@ -816,9 +884,9 @@ void tst_TouchMouse::buttonOnTouch()
// Normal touch click
QPoint p1 = QPoint(10, 110);
- QTest::touchEvent(window.data(), device).press(0, p1, window.data());
+ touchSeq.press(0, p1, window.data()).commit();
QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).release(0, p1, window.data());
+ touchSeq.release(0, p1, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(eventItem1->eventList.size(), 5);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
@@ -829,7 +897,7 @@ void tst_TouchMouse::buttonOnTouch()
eventItem1->eventList.clear();
// Normal mouse click
- QTest::mouseClick(window.data(), Qt::LeftButton, 0, p1);
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, p1);
QCOMPARE(eventItem1->eventList.size(), 3);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease);
@@ -841,9 +909,9 @@ void tst_TouchMouse::buttonOnTouch()
QPoint p2 = QPoint(60, 10);
// Start the events after each other
- QTest::touchEvent(window.data(), device).press(0, p1, window.data());
+ touchSeq.press(0, p1, window.data()).commit();
QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).stationary(0).press(1, p2, window.data());
+ touchSeq.stationary(0).press(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(button1->scale(), 1.0);
@@ -851,24 +919,24 @@ void tst_TouchMouse::buttonOnTouch()
// This event seems to be discarded, let's ignore it for now until someone digs into pincharea
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// QCOMPARE(button1->scale(), 1.5);
qDebug() << "Button scale: " << button1->scale();
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// QCOMPARE(button1->scale(), 2.0);
qDebug() << "Button scale: " << button1->scale();
- QTest::touchEvent(window.data(), device).release(0, p1, window.data()).release(1, p2, window.data());
+ touchSeq.release(0, p1, window.data()).release(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// QVERIFY(eventItem1->eventList.isEmpty());
// QCOMPARE(button1->scale(), 2.0);
@@ -882,7 +950,7 @@ void tst_TouchMouse::buttonOnTouch()
button1->setScale(1.0);
p1 = QPoint(40, 110);
p2 = QPoint(60, 110);
- QTest::touchEvent(window.data(), device).press(0, p1, window.data()).press(1, p2, window.data());
+ touchSeq.press(0, p1, window.data()).press(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(button1->scale(), 1.0);
QCOMPARE(eventItem1->eventList.count(), 2);
@@ -892,24 +960,24 @@ void tst_TouchMouse::buttonOnTouch()
// This event seems to be discarded, let's ignore it for now until someone digs into pincharea
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
//QCOMPARE(button1->scale(), 1.5);
qDebug() << button1->scale();
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
- QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data());
+ touchSeq.move(0, p1, window.data()).move(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
qDebug() << button1->scale();
//QCOMPARE(button1->scale(), 2.0);
- QTest::touchEvent(window.data(), device).release(0, p1, window.data()).release(1, p2, window.data());
+ touchSeq.release(0, p1, window.data()).release(1, p2, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// QCOMPARE(eventItem1->eventList.size(), 99);
qDebug() << button1->scale();
@@ -923,7 +991,7 @@ void tst_TouchMouse::pinchOnFlickable()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
QVERIFY(pinchArea);
@@ -1004,7 +1072,7 @@ void tst_TouchMouse::flickableOnPinch()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
QVERIFY(pinchArea);
@@ -1083,7 +1151,7 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QRect windowRect = QRect(window->position(), window->size());
QCursor::setPos(windowRect.center());
@@ -1216,7 +1284,7 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
QQuickMouseArea *bottomMouseArea =
window->rootObject()->findChild<QQuickMouseArea*>("rear mouseArea");
@@ -1256,7 +1324,7 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab()
window->show();
QQuickViewTestUtil::centerOnScreen(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
- QVERIFY(window->rootObject() != 0);
+ QVERIFY(window->rootObject() != nullptr);
EventItem *leftItem = window->rootObject()->findChild<EventItem*>("leftItem");
QVERIFY(leftItem);
@@ -1290,7 +1358,7 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab()
// has been grabbed by another item.
QCOMPARE(leftItem->eventList.size(), 1);
QCOMPARE(leftItem->eventList.at(0).type, QEvent::UngrabMouse);
- QCOMPARE(window->mouseGrabberItem(), (QQuickItem*)0);
+ QCOMPARE(window->mouseGrabberItem(), (QQuickItem*)nullptr);
}
void tst_TouchMouse::touchPointDeliveryOrder()
@@ -1315,6 +1383,7 @@ void tst_TouchMouse::touchPointDeliveryOrder()
QPoint pLeftMiddle = QPoint(200, 100);
QPoint pRightMiddle = QPoint(350, 100);
+ QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window.data(), device, false);
QVector<QQuickItem*> events;
EventItem *background = window->rootObject()->findChild<EventItem*>("background");
@@ -1330,7 +1399,7 @@ void tst_TouchMouse::touchPointDeliveryOrder()
connect(middle, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
connect(right, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
- QTest::touchEvent(window.data(), device).press(0, pLeft, window.data());
+ touchSeq.press(0, pLeft, window.data()).commit();
QQuickTouchUtils::flush(window.data());
// Touch on left, then background
@@ -1340,7 +1409,7 @@ void tst_TouchMouse::touchPointDeliveryOrder()
events.clear();
// New press events are deliverd first, the stationary point was not accepted, thus it doesn't get delivered
- QTest::touchEvent(window.data(), device).stationary(0).press(1, pRightMiddle, window.data());
+ touchSeq.stationary(0).press(1, pRightMiddle, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(events.size(), 3);
QCOMPARE(events.at(0), middle);
@@ -1348,49 +1417,49 @@ void tst_TouchMouse::touchPointDeliveryOrder()
QCOMPARE(events.at(2), background);
events.clear();
- QTest::touchEvent(window.data(), device).release(0, pLeft, window.data()).release(1, pRightMiddle, window.data());
+ touchSeq.release(0, pLeft, window.data()).release(1, pRightMiddle, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(events.size(), 0); // no accepted events
// Two presses, the first point should come first
- QTest::touchEvent(window.data(), device).press(0, pLeft, window.data()).press(1, pRight, window.data());
+ touchSeq.press(0, pLeft, window.data()).press(1, pRight, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(events.size(), 3);
QCOMPARE(events.at(0), left);
QCOMPARE(events.at(1), right);
QCOMPARE(events.at(2), background);
- QTest::touchEvent(window.data(), device).release(0, pLeft, window.data()).release(1, pRight, window.data());
+ touchSeq.release(0, pLeft, window.data()).release(1, pRight, window.data()).commit();
events.clear();
// Again, pressing right first
- QTest::touchEvent(window.data(), device).press(0, pRight, window.data()).press(1, pLeft, window.data());
+ touchSeq.press(0, pRight, window.data()).press(1, pLeft, window.data()).commit();
QQuickTouchUtils::flush(window.data());
QCOMPARE(events.size(), 3);
QCOMPARE(events.at(0), right);
QCOMPARE(events.at(1), left);
QCOMPARE(events.at(2), background);
- QTest::touchEvent(window.data(), device).release(0, pRight, window.data()).release(1, pLeft, window.data());
+ touchSeq.release(0, pRight, window.data()).release(1, pLeft, window.data()).commit();
events.clear();
// Two presses, both hitting the middle item on top, then branching left and right, then bottom
// Each target should be offered the events exactly once, middle first, left must come before right (id 0)
- QTest::touchEvent(window.data(), device).press(0, pLeftMiddle, window.data()).press(1, pRightMiddle, window.data());
+ touchSeq.press(0, pLeftMiddle, window.data()).press(1, pRightMiddle, window.data()).commit();
QCOMPARE(events.size(), 4);
QCOMPARE(events.at(0), middle);
QCOMPARE(events.at(1), left);
QCOMPARE(events.at(2), right);
QCOMPARE(events.at(3), background);
- QTest::touchEvent(window.data(), device).release(0, pLeftMiddle, window.data()).release(1, pRightMiddle, window.data());
+ touchSeq.release(0, pLeftMiddle, window.data()).release(1, pRightMiddle, window.data()).commit();
events.clear();
- QTest::touchEvent(window.data(), device).press(0, pRightMiddle, window.data()).press(1, pLeftMiddle, window.data());
+ touchSeq.press(0, pRightMiddle, window.data()).press(1, pLeftMiddle, window.data()).commit();
qDebug() << events;
QCOMPARE(events.size(), 4);
QCOMPARE(events.at(0), middle);
QCOMPARE(events.at(1), right);
QCOMPARE(events.at(2), left);
QCOMPARE(events.at(3), background);
- QTest::touchEvent(window.data(), device).release(0, pRightMiddle, window.data()).release(1, pLeftMiddle, window.data());
+ touchSeq.release(0, pRightMiddle, window.data()).release(1, pLeftMiddle, window.data()).commit();
}
void tst_TouchMouse::hoverEnabled()
@@ -1406,13 +1475,13 @@ void tst_TouchMouse::hoverEnabled()
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickItem *root = window->rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
QQuickMouseArea *mouseArea1 = root->findChild<QQuickMouseArea*>("mouseArea1");
- QVERIFY(mouseArea1 != 0);
+ QVERIFY(mouseArea1 != nullptr);
QQuickMouseArea *mouseArea2 = root->findChild<QQuickMouseArea*>("mouseArea2");
- QVERIFY(mouseArea2 != 0);
+ QVERIFY(mouseArea2 != nullptr);
QSignalSpy enterSpy1(mouseArea1, SIGNAL(entered()));
QSignalSpy exitSpy1(mouseArea1, SIGNAL(exited()));
@@ -1489,7 +1558,7 @@ void tst_TouchMouse::implicitUngrab()
QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickItem *root = window->rootObject();
- QVERIFY(root != 0);
+ QVERIFY(root != nullptr);
EventItem *eventItem = root->findChild<EventItem*>("eventItem1");
eventItem->acceptMouse = true;
QPoint p1(20, 20);