summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/corelib/ipc/localfortuneclient/client.cpp67
-rw-r--r--examples/corelib/ipc/localfortuneclient/client.h13
-rw-r--r--examples/corelib/ipc/localfortuneclient/main.cpp1
-rw-r--r--examples/corelib/ipc/localfortuneserver/main.cpp2
-rw-r--r--examples/corelib/ipc/localfortuneserver/server.cpp36
-rw-r--r--examples/corelib/ipc/localfortuneserver/server.h4
-rw-r--r--examples/corelib/ipc/sharedmemory/sharedmemory.pro1
-rw-r--r--examples/corelib/json/savegame/character.cpp28
-rw-r--r--examples/corelib/json/savegame/character.h6
-rw-r--r--examples/corelib/json/savegame/doc/src/savegame.qdoc37
-rw-r--r--examples/corelib/json/savegame/game.cpp86
-rw-r--r--examples/corelib/json/savegame/game.h12
-rw-r--r--examples/corelib/json/savegame/level.cpp44
-rw-r--r--examples/corelib/json/savegame/level.h16
-rw-r--r--examples/corelib/json/savegame/main.cpp28
-rw-r--r--examples/corelib/mimetypes/mimetypebrowser/mimetypebrowser.pro1
-rw-r--r--examples/corelib/threads/queuedcustomtype/main.cpp1
-rw-r--r--examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro1
-rw-r--r--examples/corelib/threads/queuedcustomtype/renderthread.cpp6
-rw-r--r--examples/corelib/threads/semaphores/semaphores.cpp3
-rw-r--r--examples/corelib/threads/waitconditions/waitconditions.cpp4
-rw-r--r--examples/corelib/tools/contiguouscache/contiguouscache.pro1
-rw-r--r--examples/corelib/tools/contiguouscache/randomlistmodel.cpp3
-rw-r--r--examples/dbus/remotecontrolledcar/car/car.cpp8
-rw-r--r--examples/embedded/flickable/main.cpp2
-rw-r--r--examples/embedded/lightmaps/lightmaps.cpp6
-rw-r--r--examples/embedded/lightmaps/slippymap.cpp14
-rw-r--r--examples/embedded/raycasting/raycasting.cpp7
-rw-r--r--examples/examples.pro7
-rw-r--r--examples/gui/rasterwindow/rasterwindow.cpp1
-rw-r--r--examples/network/bearermonitor/bearermonitor.pro1
-rw-r--r--examples/network/broadcastreceiver/broadcastreceiver.pro1
-rw-r--r--examples/network/broadcastreceiver/receiver.cpp14
-rw-r--r--examples/network/broadcastreceiver/receiver.h11
-rw-r--r--examples/network/broadcastsender/broadcastsender.pro1
-rw-r--r--examples/network/broadcastsender/sender.cpp22
-rw-r--r--examples/network/broadcastsender/sender.h19
-rw-r--r--examples/network/doc/images/http-example.pngbin7006 -> 8099 bytes
-rw-r--r--examples/network/download/main.cpp58
-rw-r--r--examples/network/downloadmanager/downloadmanager.cpp58
-rw-r--r--examples/network/downloadmanager/downloadmanager.h23
-rw-r--r--examples/network/downloadmanager/main.cpp8
-rw-r--r--examples/network/downloadmanager/textprogressbar.cpp13
-rw-r--r--examples/network/downloadmanager/textprogressbar.h10
-rw-r--r--examples/network/fortuneclient/client.cpp19
-rw-r--r--examples/network/fortuneclient/client.h18
-rw-r--r--examples/network/fortuneclient/fortuneclient.pro1
-rw-r--r--examples/network/fortuneclient/main.cpp4
-rw-r--r--examples/network/fortuneserver/main.cpp8
-rw-r--r--examples/network/fortuneserver/server.cpp79
-rw-r--r--examples/network/fortuneserver/server.h15
-rw-r--r--examples/network/googlesuggest/googlesuggest.cpp36
-rw-r--r--examples/network/googlesuggest/googlesuggest.h19
-rw-r--r--examples/network/googlesuggest/googlesuggest.pro1
-rw-r--r--examples/network/googlesuggest/main.cpp6
-rw-r--r--examples/network/googlesuggest/searchbox.cpp8
-rw-r--r--examples/network/googlesuggest/searchbox.h6
-rw-r--r--examples/network/http/httpwindow.cpp46
-rw-r--r--examples/network/http/httpwindow.h8
-rw-r--r--examples/network/multicastreceiver/multicastreceiver.pro1
-rw-r--r--examples/network/multicastreceiver/receiver.cpp59
-rw-r--r--examples/network/multicastreceiver/receiver.h16
-rw-r--r--examples/network/multicastsender/multicastsender.pro1
-rw-r--r--examples/network/multicastsender/sender.cpp54
-rw-r--r--examples/network/multicastsender/sender.h36
-rw-r--r--examples/network/network-chat/network-chat.pro2
-rw-r--r--examples/network/securesocketclient/certificateinfo.cpp22
-rw-r--r--examples/network/securesocketclient/certificateinfo.h13
-rw-r--r--examples/network/securesocketclient/certificateinfo.ui2
-rw-r--r--examples/network/securesocketclient/main.cpp7
-rw-r--r--examples/network/securesocketclient/securesocketclient.pro4
-rw-r--r--examples/network/securesocketclient/sslclient.cpp168
-rw-r--r--examples/network/securesocketclient/sslclient.h25
-rw-r--r--examples/network/securesocketclient/sslclient.ui10
-rw-r--r--examples/network/threadedfortuneserver/fortuneserver.cpp4
-rw-r--r--examples/network/threadedfortuneserver/main.cpp1
-rw-r--r--examples/network/torrent/main.cpp1
-rw-r--r--examples/network/torrent/torrent.pro1
-rw-r--r--examples/network/torrent/torrentclient.cpp22
-rw-r--r--examples/opengl/contextinfo/contextinfo.pro1
-rw-r--r--examples/opengl/hellowindow/hellowindow.cpp34
-rw-r--r--examples/opengl/hellowindow/hellowindow.h2
-rw-r--r--examples/opengl/legacy/framebufferobject2/glwidget.cpp5
-rw-r--r--examples/opengl/legacy/grabber/glwidget.cpp16
-rw-r--r--examples/opengl/legacy/overpainting/bubble.cpp10
-rw-r--r--examples/opengl/legacy/overpainting/glwidget.cpp12
-rw-r--r--examples/opengl/legacy/pbuffers2/glwidget.cpp35
-rw-r--r--examples/opengl/legacy/samplebuffers/glwidget.cpp26
-rw-r--r--examples/opengl/qopenglwidget/bubble.cpp8
-rw-r--r--examples/opengl/qopenglwidget/glwidget.cpp43
-rw-r--r--examples/opengl/qopenglwidget/main.cpp4
-rw-r--r--examples/opengl/qopenglwidget/mainwindow.cpp5
-rw-r--r--examples/opengl/qopenglwindow/background.frag2
-rw-r--r--examples/opengl/threadedqopenglwidget/glwidget.cpp26
-rw-r--r--examples/qtconcurrent/imagescaling/imagescaling.pro1
-rw-r--r--examples/sql/books/books.pro1
-rw-r--r--examples/sql/cachedtable/cachedtable.pro1
-rw-r--r--examples/sql/doc/src/drilldown.qdoc2
-rw-r--r--examples/sql/drilldown/drilldown.pro1
-rw-r--r--examples/sql/masterdetail/masterdetail.pro1
-rw-r--r--examples/sql/querymodel/querymodel.pro1
-rw-r--r--examples/sql/relationaltablemodel/relationaltablemodel.pro1
-rw-r--r--examples/sql/sqlbrowser/sqlbrowser.pro1
-rw-r--r--examples/sql/sqlwidgetmapper/sqlwidgetmapper.pro1
-rw-r--r--examples/sql/tablemodel/tablemodel.pro1
-rw-r--r--examples/touch/fingerpaint/fingerpaint.pro1
-rw-r--r--examples/touch/pinchzoom/main.cpp1
-rw-r--r--examples/touch/pinchzoom/mouse.cpp30
-rw-r--r--examples/vulkan/doc/images/hellovulkancubes.pngbin0 -> 98495 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkantexture.pngbin0 -> 10259 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkantriangle.pngbin0 -> 30952 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkanwidget.pngbin0 -> 25256 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkanwindow.pngbin0 -> 2736 bytes
-rw-r--r--examples/vulkan/doc/src/hellovulkancubes.qdoc58
-rw-r--r--examples/vulkan/doc/src/hellovulkantexture.qdoc (renamed from examples/widgets/doc/src/configdialog.qdoc)18
-rw-r--r--examples/vulkan/doc/src/hellovulkantriangle.qdoc (renamed from examples/widgets/doc/src/lighting.qdoc)26
-rw-r--r--examples/vulkan/doc/src/hellovulkanwidget.qdoc (renamed from examples/widgets/doc/src/appchooser.qdoc)25
-rw-r--r--examples/vulkan/doc/src/hellovulkanwindow.qdoc101
-rw-r--r--examples/vulkan/hellovulkancubes/camera.cpp112
-rw-r--r--examples/vulkan/hellovulkancubes/camera.h (renamed from examples/widgets/effects/lighting/lighting.h)42
-rw-r--r--examples/vulkan/hellovulkancubes/color.frag12
-rw-r--r--examples/vulkan/hellovulkancubes/color.vert14
-rw-r--r--examples/vulkan/hellovulkancubes/color_frag.spvbin0 -> 616 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong.frag39
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong.vert32
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong_frag.spvbin0 -> 3364 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong_vert.spvbin0 -> 2268 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_vert.spvbin0 -> 744 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/hellovulkancubes.pro24
-rw-r--r--examples/vulkan/hellovulkancubes/hellovulkancubes.qrc10
-rw-r--r--examples/vulkan/hellovulkancubes/main.cpp92
-rw-r--r--examples/vulkan/hellovulkancubes/mainwindow.cpp117
-rw-r--r--examples/vulkan/hellovulkancubes/mainwindow.h (renamed from examples/widgets/dialogs/configdialog/configdialog.h)38
-rw-r--r--examples/vulkan/hellovulkancubes/mesh.cpp98
-rw-r--r--examples/vulkan/hellovulkancubes/mesh.h (renamed from examples/widgets/dialogs/configdialog/pages.h)33
-rw-r--r--examples/vulkan/hellovulkancubes/renderer.cpp1048
-rw-r--r--examples/vulkan/hellovulkancubes/renderer.h158
-rw-r--r--examples/vulkan/hellovulkancubes/shader.cpp94
-rw-r--r--examples/vulkan/hellovulkancubes/shader.h (renamed from examples/widgets/effects/lighting/main.cpp)34
-rw-r--r--examples/vulkan/hellovulkancubes/vulkanwindow.cpp134
-rw-r--r--examples/vulkan/hellovulkancubes/vulkanwindow.h85
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.cpp829
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.h108
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.pro7
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.qrc7
-rw-r--r--examples/vulkan/hellovulkantexture/main.cpp91
-rw-r--r--examples/vulkan/hellovulkantexture/qt256.pngbin0 -> 6208 bytes
-rw-r--r--examples/vulkan/hellovulkantexture/texture.frag12
-rw-r--r--examples/vulkan/hellovulkantexture/texture.vert18
-rw-r--r--examples/vulkan/hellovulkantexture/texture_frag.spvbin0 -> 556 bytes
-rw-r--r--examples/vulkan/hellovulkantexture/texture_vert.spvbin0 -> 968 bytes
-rw-r--r--examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro12
-rw-r--r--examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc6
-rw-r--r--examples/vulkan/hellovulkantriangle/main.cpp100
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp185
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.h100
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro16
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc6
-rw-r--r--examples/vulkan/hellovulkanwidget/main.cpp112
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp128
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.h77
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro6
-rw-r--r--examples/vulkan/hellovulkanwindow/main.cpp93
-rw-r--r--examples/vulkan/shared/block.bufbin0 -> 4256 bytes
-rw-r--r--examples/vulkan/shared/block.txt100
-rw-r--r--examples/vulkan/shared/color.frag10
-rw-r--r--examples/vulkan/shared/color.vert18
-rw-r--r--examples/vulkan/shared/color_frag.spvbin0 -> 496 bytes
-rw-r--r--examples/vulkan/shared/color_vert.spvbin0 -> 960 bytes
-rw-r--r--examples/vulkan/shared/objconvert.js241
-rw-r--r--examples/vulkan/shared/qt_logo.bufbin0 -> 125600 bytes
-rw-r--r--examples/vulkan/shared/qt_logo.txt2912
-rw-r--r--examples/vulkan/shared/trianglerenderer.cpp513
-rw-r--r--examples/vulkan/shared/trianglerenderer.h85
-rw-r--r--examples/vulkan/vulkan.pro10
-rw-r--r--examples/widgets/animation/animatedtiles/main.cpp19
-rw-r--r--examples/widgets/animation/animation.pro1
-rw-r--r--examples/widgets/animation/appchooser/accessories-dictionary.pngbin5396 -> 0 bytes
-rw-r--r--examples/widgets/animation/appchooser/akregator.pngbin4873 -> 0 bytes
-rw-r--r--examples/widgets/animation/appchooser/appchooser.pro8
-rw-r--r--examples/widgets/animation/appchooser/appchooser.qrc8
-rw-r--r--examples/widgets/animation/appchooser/digikam.pngbin3334 -> 0 bytes
-rw-r--r--examples/widgets/animation/appchooser/k3b.pngbin8220 -> 0 bytes
-rw-r--r--examples/widgets/animation/appchooser/main.cpp183
-rw-r--r--examples/widgets/animation/easing/easing.pro1
-rw-r--r--examples/widgets/animation/easing/images/qt-logo.pngbin1495 -> 1165 bytes
-rw-r--r--examples/widgets/animation/moveblocks/main.cpp4
-rw-r--r--examples/widgets/animation/stickman/lifecycle.cpp3
-rw-r--r--examples/widgets/animation/stickman/stickman.cpp10
-rw-r--r--examples/widgets/animation/sub-attaq/main.cpp2
-rw-r--r--examples/widgets/animation/sub-attaq/states.cpp7
-rw-r--r--examples/widgets/animation/sub-attaq/submarine_p.h5
-rw-r--r--examples/widgets/desktop/screenshot/screenshot.pro1
-rw-r--r--examples/widgets/desktop/systray/systray.pro1
-rw-r--r--examples/widgets/dialogs/configdialog/configdialog.cpp124
-rw-r--r--examples/widgets/dialogs/configdialog/configdialog.pro12
-rw-r--r--examples/widgets/dialogs/configdialog/configdialog.qrc7
-rw-r--r--examples/widgets/dialogs/configdialog/images/config.pngbin6758 -> 0 bytes
-rw-r--r--examples/widgets/dialogs/configdialog/images/query.pngbin2116 -> 0 bytes
-rw-r--r--examples/widgets/dialogs/configdialog/images/update.pngbin7890 -> 0 bytes
-rw-r--r--examples/widgets/dialogs/configdialog/pages.cpp161
-rw-r--r--examples/widgets/dialogs/dialogs.pro2
-rw-r--r--examples/widgets/dialogs/findfiles/findfiles.pro1
-rw-r--r--examples/widgets/dialogs/findfiles/window.cpp57
-rw-r--r--examples/widgets/dialogs/findfiles/window.h2
-rw-r--r--examples/widgets/dialogs/standarddialogs/standarddialogs.pro1
-rw-r--r--examples/widgets/dialogs/tabdialog/tabdialog.pro1
-rw-r--r--examples/widgets/doc/images/addressbook-editdialog.pngbin8669 -> 11374 bytes
-rw-r--r--examples/widgets/doc/images/addressbook-example.pngbin12388 -> 20047 bytes
-rw-r--r--examples/widgets/doc/images/addressbook-newaddresstab.pngbin12556 -> 17413 bytes
-rw-r--r--examples/widgets/doc/images/graphicssimpleanchorlayout-example.pngbin16743 -> 11301 bytes
-rw-r--r--examples/widgets/doc/images/itemviews-editabletreemodel.pngbin32534 -> 30556 bytes
-rw-r--r--examples/widgets/doc/images/notepad.pngbin0 -> 12418 bytes
-rw-r--r--examples/widgets/doc/images/notepad1.pngbin0 -> 12418 bytes
-rw-r--r--examples/widgets/doc/images/notepad2.pngbin0 -> 22700 bytes
-rw-r--r--examples/widgets/doc/images/notepad3.pngbin0 -> 40584 bytes
-rw-r--r--examples/widgets/doc/images/notepad4.pngbin0 -> 9494 bytes
-rw-r--r--examples/widgets/doc/images/notepad_menu.pngbin0 -> 8657 bytes
-rw-r--r--examples/widgets/doc/images/stylesheet-pagefold.pngbin15989 -> 29118 bytes
-rw-r--r--examples/widgets/doc/src/addressbook.qdoc43
-rw-r--r--examples/widgets/doc/src/basiclayouts.qdoc6
-rw-r--r--examples/widgets/doc/src/blurpicker.qdoc9
-rw-r--r--examples/widgets/doc/src/calendarwidget.qdoc10
-rw-r--r--examples/widgets/doc/src/collidingmice-example.qdoc10
-rw-r--r--examples/widgets/doc/src/customsortfiltermodel.qdoc6
-rw-r--r--examples/widgets/doc/src/dragdroprobot.qdoc2
-rw-r--r--examples/widgets/doc/src/draggabletext.qdoc1
-rw-r--r--examples/widgets/doc/src/easing.qdoc3
-rw-r--r--examples/widgets/doc/src/elasticnodes.qdoc9
-rw-r--r--examples/widgets/doc/src/findfiles.qdoc41
-rw-r--r--examples/widgets/doc/src/graphicsview-anchorlayout.qdoc43
-rw-r--r--examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc46
-rw-r--r--examples/widgets/doc/src/painterpaths.qdoc11
-rw-r--r--examples/widgets/doc/src/stardelegate.qdoc16
-rw-r--r--examples/widgets/doc/src/stylesheet.qdoc51
-rw-r--r--examples/widgets/doc/src/tablet.qdoc13
-rw-r--r--examples/widgets/doc/src/validators.qdoc2
-rw-r--r--examples/widgets/draganddrop/draggableicons/dragwidget.h2
-rw-r--r--examples/widgets/draganddrop/draggabletext/dragwidget.cpp4
-rw-r--r--examples/widgets/draganddrop/draggabletext/dragwidget.h2
-rw-r--r--examples/widgets/draganddrop/dropsite/droparea.h4
-rw-r--r--examples/widgets/draganddrop/dropsite/dropsite.pro1
-rw-r--r--examples/widgets/draganddrop/dropsite/dropsitewindow.cpp6
-rw-r--r--examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp2
-rw-r--r--examples/widgets/draganddrop/fridgemagnets/dragwidget.h2
-rw-r--r--examples/widgets/draganddrop/puzzle/main.cpp4
-rw-r--r--examples/widgets/draganddrop/puzzle/mainwindow.cpp27
-rw-r--r--examples/widgets/draganddrop/puzzle/mainwindow.h4
-rw-r--r--examples/widgets/draganddrop/puzzle/pieceslist.cpp2
-rw-r--r--examples/widgets/draganddrop/puzzle/pieceslist.h4
-rw-r--r--examples/widgets/draganddrop/puzzle/puzzle.pro1
-rw-r--r--examples/widgets/draganddrop/puzzle/puzzlewidget.cpp65
-rw-r--r--examples/widgets/draganddrop/puzzle/puzzlewidget.h15
-rw-r--r--examples/widgets/effects/blurpicker/blurpicker.cpp9
-rw-r--r--examples/widgets/effects/effects.pro1
-rw-r--r--examples/widgets/effects/lighting/lighting.cpp150
-rw-r--r--examples/widgets/effects/lighting/lighting.pro8
-rw-r--r--examples/widgets/gestures/imagegestures/imagegestures.pro1
-rw-r--r--examples/widgets/graphicsview/boxes/boxes.pro1
-rw-r--r--examples/widgets/graphicsview/boxes/glbuffers.cpp4
-rw-r--r--examples/widgets/graphicsview/boxes/qtbox.cpp2
-rw-r--r--examples/widgets/graphicsview/boxes/scene.cpp15
-rw-r--r--examples/widgets/graphicsview/boxes/scene.h2
-rw-r--r--examples/widgets/graphicsview/boxes/trackball.cpp8
-rw-r--r--examples/widgets/graphicsview/collidingmice/main.cpp1
-rw-r--r--examples/widgets/graphicsview/collidingmice/mouse.cpp30
-rw-r--r--examples/widgets/graphicsview/diagramscene/arrow.cpp17
-rw-r--r--examples/widgets/graphicsview/diagramscene/diagramscene.pro1
-rw-r--r--examples/widgets/graphicsview/dragdroprobot/coloritem.cpp4
-rw-r--r--examples/widgets/graphicsview/dragdroprobot/main.cpp1
-rw-r--r--examples/widgets/graphicsview/elasticnodes/edge.cpp28
-rw-r--r--examples/widgets/graphicsview/elasticnodes/graphwidget.cpp3
-rw-r--r--examples/widgets/graphicsview/elasticnodes/main.cpp1
-rw-r--r--examples/widgets/graphicsview/embeddeddialogs/embeddeddialogs.pro1
-rw-r--r--examples/widgets/graphicsview/padnavigator/padnavigator.pro1
-rw-r--r--examples/widgets/itemviews/addressbook/addressbook.pro1
-rw-r--r--examples/widgets/itemviews/addressbook/addresswidget.cpp26
-rw-r--r--examples/widgets/itemviews/addressbook/tablemodel.cpp37
-rw-r--r--examples/widgets/itemviews/addressbook/tablemodel.h29
-rw-r--r--examples/widgets/itemviews/basicsortfiltermodel/basicsortfiltermodel.pro1
-rw-r--r--examples/widgets/itemviews/chart/chart.pro1
-rw-r--r--examples/widgets/itemviews/chart/pieview.cpp12
-rw-r--r--examples/widgets/itemviews/coloreditorfactory/coloreditorfactory.pro1
-rw-r--r--examples/widgets/itemviews/combowidgetmapper/combowidgetmapper.pro1
-rw-r--r--examples/widgets/itemviews/customsortfiltermodel/customsortfiltermodel.pro1
-rw-r--r--examples/widgets/itemviews/dirview/dirview.pro1
-rw-r--r--examples/widgets/itemviews/editabletreemodel/editabletreemodel.pro1
-rw-r--r--examples/widgets/itemviews/fetchmore/fetchmore.pro1
-rw-r--r--examples/widgets/itemviews/frozencolumn/frozencolumn.pro1
-rw-r--r--examples/widgets/itemviews/interview/interview.pro1
-rw-r--r--examples/widgets/itemviews/pixelator/pixelator.pro1
-rw-r--r--examples/widgets/itemviews/puzzle/main.cpp2
-rw-r--r--examples/widgets/itemviews/puzzle/mainwindow.cpp33
-rw-r--r--examples/widgets/itemviews/puzzle/mainwindow.h2
-rw-r--r--examples/widgets/itemviews/puzzle/piecesmodel.cpp3
-rw-r--r--examples/widgets/itemviews/puzzle/puzzle.pro1
-rw-r--r--examples/widgets/itemviews/puzzle/puzzlewidget.cpp57
-rw-r--r--examples/widgets/itemviews/puzzle/puzzlewidget.h16
-rw-r--r--examples/widgets/itemviews/simpledommodel/simpledommodel.pro1
-rw-r--r--examples/widgets/itemviews/simpletreemodel/simpletreemodel.pro1
-rw-r--r--examples/widgets/itemviews/simplewidgetmapper/simplewidgetmapper.pro1
-rw-r--r--examples/widgets/itemviews/spinboxdelegate/spinboxdelegate.pro1
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheet.pro1
-rw-r--r--examples/widgets/itemviews/stardelegate/stardelegate.pro1
-rw-r--r--examples/widgets/itemviews/storageview/main.cpp10
-rw-r--r--examples/widgets/itemviews/storageview/storagemodel.cpp79
-rw-r--r--examples/widgets/itemviews/storageview/storagemodel.h14
-rw-r--r--examples/widgets/itemviews/storageview/storageview.pro1
-rw-r--r--examples/widgets/layouts/basiclayouts/basiclayouts.pro1
-rw-r--r--examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pro1
-rw-r--r--examples/widgets/mainwindows/application/application.pro1
-rw-r--r--examples/widgets/mainwindows/dockwidgets/dockwidgets.pro1
-rw-r--r--examples/widgets/mainwindows/mainwindow/mainwindow.cpp1
-rw-r--r--examples/widgets/mainwindows/mainwindow/mainwindow.pro1
-rw-r--r--examples/widgets/mainwindows/mainwindow/toolbar.cpp4
-rw-r--r--examples/widgets/mainwindows/mdi/mdi.pro1
-rw-r--r--examples/widgets/mainwindows/sdi/sdi.pro1
-rw-r--r--examples/widgets/painting/affine/xform.cpp48
-rw-r--r--examples/widgets/painting/basicdrawing/basicdrawing.pro1
-rw-r--r--examples/widgets/painting/composition/composition.cpp2
-rw-r--r--examples/widgets/painting/fontsampler/fontsampler.pro1
-rw-r--r--examples/widgets/painting/imagecomposition/imagecomposition.pro1
-rw-r--r--examples/widgets/painting/painterpaths/painterpaths.pro1
-rw-r--r--examples/widgets/painting/painterpaths/window.cpp10
-rw-r--r--examples/widgets/painting/transformations/transformations.pro1
-rw-r--r--examples/widgets/richtext/calendar/calendar.pro1
-rw-r--r--examples/widgets/richtext/orderform/orderform.pro1
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro1
-rw-r--r--examples/widgets/richtext/textedit/textedit.pro1
-rw-r--r--examples/widgets/statemachine/rogue/window.cpp4
-rw-r--r--examples/widgets/tools/codecs/codecs.pro1
-rw-r--r--examples/widgets/tools/completer/completer.pro1
-rw-r--r--examples/widgets/tools/customcompleter/customcompleter.pro1
-rw-r--r--examples/widgets/tools/i18n/i18n.pro1
-rw-r--r--examples/widgets/tools/plugandpaint/plugandpaint.pro3
-rw-r--r--examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp10
-rw-r--r--examples/widgets/tools/regexp/regexp.pro1
-rw-r--r--examples/widgets/tools/regularexpression/regularexpression.pro1
-rw-r--r--examples/widgets/tools/settingseditor/settingseditor.pro1
-rw-r--r--examples/widgets/tools/treemodelcompleter/treemodelcompleter.pro1
-rw-r--r--examples/widgets/tools/undo/mainwindow.cpp11
-rw-r--r--examples/widgets/tools/undo/undo.pro1
-rw-r--r--examples/widgets/tools/undoframework/diagramitem.cpp3
-rw-r--r--examples/widgets/tools/undoframework/undoframework.pro1
-rw-r--r--examples/widgets/tutorials/addressbook/part6/part6.pro1
-rw-r--r--examples/widgets/tutorials/addressbook/part7/part7.pro1
-rw-r--r--examples/widgets/tutorials/gettingStarted/gsQt/part5/part5.pro2
-rw-r--r--examples/widgets/tutorials/gettingstartedqt.qdoc559
-rw-r--r--examples/widgets/tutorials/modelview/1_readonly/1_readonly.pro1
-rw-r--r--examples/widgets/tutorials/modelview/2_formatting/2_formatting.pro1
-rw-r--r--examples/widgets/tutorials/modelview/3_changingmodel/3_changingmodel.pro1
-rw-r--r--examples/widgets/tutorials/modelview/4_headers/4_headers.pro1
-rw-r--r--examples/widgets/tutorials/modelview/5_edit/5_edit.pro1
-rw-r--r--examples/widgets/tutorials/modelview/6_treeview/6_treeview.pro1
-rw-r--r--examples/widgets/tutorials/modelview/7_selections/7_selections.pro1
-rw-r--r--examples/widgets/tutorials/notepad/images/copy.pngbin0 -> 1633 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/create.pngbin0 -> 459 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/cut.pngbin0 -> 9554 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/edit_redo.pngbin0 -> 7463 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/edit_undo.pngbin0 -> 8424 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/exit.pngbin0 -> 379 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/font.pngbin0 -> 6983 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/info.pngbin0 -> 557 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/new.pngbin0 -> 7422 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/open.pngbin0 -> 5437 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/paste.pngbin0 -> 3597 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/pencil.pngbin0 -> 3780 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/print.pngbin0 -> 331 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/save.pngbin0 -> 2699 bytes
-rw-r--r--examples/widgets/tutorials/notepad/images/save_as.pngbin0 -> 8209 bytes
-rw-r--r--examples/widgets/tutorials/notepad/main.cpp (renamed from examples/widgets/dialogs/configdialog/main.cpp)16
-rw-r--r--examples/widgets/tutorials/notepad/notepad.cpp193
-rw-r--r--examples/widgets/tutorials/notepad/notepad.h114
-rw-r--r--examples/widgets/tutorials/notepad/notepad.pro21
-rw-r--r--examples/widgets/tutorials/notepad/notepad.qrc19
-rw-r--r--examples/widgets/tutorials/notepad/notepad.ui196
-rw-r--r--examples/widgets/tutorials/tutorials.pro2
-rw-r--r--examples/widgets/tutorials/widgets/nestedlayouts/nestedlayouts.pro1
-rw-r--r--examples/widgets/widgets/calendarwidget/calendarwidget.pro1
-rw-r--r--examples/widgets/widgets/charactermap/charactermap.pro1
-rw-r--r--examples/widgets/widgets/elidedlabel/elidedlabel.pro1
-rw-r--r--examples/widgets/widgets/icons/icons.pro1
-rw-r--r--examples/widgets/widgets/imageviewer/imageviewer.pro1
-rw-r--r--examples/widgets/widgets/lineedits/lineedits.pro1
-rw-r--r--examples/widgets/widgets/movie/movie.pro1
-rw-r--r--examples/widgets/widgets/scribble/scribble.pro1
-rw-r--r--examples/widgets/widgets/sliders/sliders.pro1
-rw-r--r--examples/widgets/widgets/spinboxes/spinboxes.pro1
-rw-r--r--examples/widgets/widgets/styles/styles.pro1
-rw-r--r--examples/widgets/widgets/stylesheet/stylesheet.pro1
-rw-r--r--examples/widgets/widgets/tablet/mainwindow.cpp10
-rw-r--r--examples/widgets/widgets/tablet/mainwindow.h1
-rw-r--r--examples/widgets/widgets/tablet/tablet.pro1
-rw-r--r--examples/widgets/widgets/tablet/tabletcanvas.cpp52
-rw-r--r--examples/widgets/widgets/tablet/tabletcanvas.h2
-rw-r--r--examples/widgets/widgets/tetrix/main.cpp1
-rw-r--r--examples/widgets/widgets/tetrix/tetrixpiece.cpp2
-rw-r--r--examples/widgets/widgets/tooltips/main.cpp1
-rw-r--r--examples/widgets/widgets/tooltips/sortingbox.cpp4
-rw-r--r--examples/widgets/widgets/validators/validators.pro1
-rw-r--r--examples/xml/dombookmarks/dombookmarks.pro1
-rw-r--r--examples/xml/dombookmarks/mainwindow.cpp44
-rw-r--r--examples/xml/dombookmarks/mainwindow.h9
-rw-r--r--examples/xml/dombookmarks/xbeltree.cpp74
-rw-r--r--examples/xml/dombookmarks/xbeltree.h11
-rw-r--r--examples/xml/rsslisting/rsslisting.pro1
-rw-r--r--examples/xml/saxbookmarks/mainwindow.cpp67
-rw-r--r--examples/xml/saxbookmarks/mainwindow.h13
-rw-r--r--examples/xml/saxbookmarks/saxbookmarks.pro1
-rw-r--r--examples/xml/saxbookmarks/xbelgenerator.cpp18
-rw-r--r--examples/xml/saxbookmarks/xbelgenerator.h6
-rw-r--r--examples/xml/saxbookmarks/xbelhandler.cpp28
-rw-r--r--examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc2
-rw-r--r--examples/xml/streambookmarks/mainwindow.cpp75
-rw-r--r--examples/xml/streambookmarks/mainwindow.h13
-rw-r--r--examples/xml/streambookmarks/streambookmarks.pro1
-rw-r--r--examples/xml/streambookmarks/xbelreader.cpp36
-rw-r--r--examples/xml/streambookmarks/xbelreader.h4
-rw-r--r--examples/xml/streambookmarks/xbelwriter.cpp29
-rw-r--r--examples/xml/streambookmarks/xbelwriter.h6
420 files changed, 11198 insertions, 2226 deletions
diff --git a/examples/corelib/ipc/localfortuneclient/client.cpp b/examples/corelib/ipc/localfortuneclient/client.cpp
index d5a1525769..8d415f73aa 100644
--- a/examples/corelib/ipc/localfortuneclient/client.cpp
+++ b/examples/corelib/ipc/localfortuneclient/client.cpp
@@ -54,45 +54,45 @@
#include "client.h"
Client::Client(QWidget *parent)
- : QDialog(parent)
+ : QDialog(parent),
+ hostLineEdit(new QLineEdit("fortune")),
+ getFortuneButton(new QPushButton(tr("Get Fortune"))),
+ statusLabel(new QLabel(tr("This examples requires that you run the "
+ "Local Fortune Server example as well."))),
+ socket(new QLocalSocket(this))
{
- hostLabel = new QLabel(tr("&Server name:"));
- hostLineEdit = new QLineEdit("fortune");
-
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ QLabel *hostLabel = new QLabel(tr("&Server name:"));
hostLabel->setBuddy(hostLineEdit);
- statusLabel = new QLabel(tr("This examples requires that you run the "
- "Fortune Server example as well."));
statusLabel->setWordWrap(true);
- getFortuneButton = new QPushButton(tr("Get Fortune"));
getFortuneButton->setDefault(true);
+ QPushButton *quitButton = new QPushButton(tr("Quit"));
- quitButton = new QPushButton(tr("Quit"));
-
- buttonBox = new QDialogButtonBox;
+ QDialogButtonBox *buttonBox = new QDialogButtonBox;
buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
- socket = new QLocalSocket(this);
+ in.setDevice(socket);
+ in.setVersion(QDataStream::Qt_5_10);
- connect(hostLineEdit, SIGNAL(textChanged(QString)),
- this, SLOT(enableGetFortuneButton()));
- connect(getFortuneButton, SIGNAL(clicked()),
- this, SLOT(requestNewFortune()));
- connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
- connect(socket, SIGNAL(readyRead()), this, SLOT(readFortune()));
- connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
- this, SLOT(displayError(QLocalSocket::LocalSocketError)));
+ connect(hostLineEdit, &QLineEdit::textChanged,
+ this, &Client::enableGetFortuneButton);
+ connect(getFortuneButton, &QPushButton::clicked,
+ this, &Client::requestNewFortune);
+ connect(quitButton, &QPushButton::clicked, this, &Client::close);
+ connect(socket, &QLocalSocket::readyRead, this, &Client::readFortune);
+ connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
+ this, &Client::displayError);
- QGridLayout *mainLayout = new QGridLayout;
+ QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->addWidget(hostLabel, 0, 0);
mainLayout->addWidget(hostLineEdit, 0, 1);
mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
- setLayout(mainLayout);
- setWindowTitle(tr("Fortune Client"));
+ setWindowTitle(QGuiApplication::applicationDisplayName());
hostLineEdit->setFocus();
}
@@ -106,11 +106,9 @@ void Client::requestNewFortune()
void Client::readFortune()
{
- QDataStream in(socket);
- in.setVersion(QDataStream::Qt_4_0);
-
if (blockSize == 0) {
- // Relies on the fact that QDataStream format streams a quint32 into sizeof(quint32) bytes
+ // Relies on the fact that QDataStream serializes a quint32 into
+ // sizeof(quint32) bytes
if (socket->bytesAvailable() < (int)sizeof(quint32))
return;
in >> blockSize;
@@ -123,7 +121,7 @@ void Client::readFortune()
in >> nextFortune;
if (nextFortune == currentFortune) {
- QTimer::singleShot(0, this, SLOT(requestNewFortune()));
+ QTimer::singleShot(0, this, &Client::requestNewFortune);
return;
}
@@ -136,21 +134,22 @@ void Client::displayError(QLocalSocket::LocalSocketError socketError)
{
switch (socketError) {
case QLocalSocket::ServerNotFoundError:
- QMessageBox::information(this, tr("Fortune Client"),
- tr("The host was not found. Please check the "
- "host name and port settings."));
+ QMessageBox::information(this, tr("Local Fortune Client"),
+ tr("The host was not found. Please make sure "
+ "that the server is running and that the "
+ "server name is correct."));
break;
case QLocalSocket::ConnectionRefusedError:
- QMessageBox::information(this, tr("Fortune Client"),
+ QMessageBox::information(this, tr("Local Fortune Client"),
tr("The connection was refused by the peer. "
"Make sure the fortune server is running, "
- "and check that the host name and port "
- "settings are correct."));
+ "and check that the server name "
+ "is correct."));
break;
case QLocalSocket::PeerClosedError:
break;
default:
- QMessageBox::information(this, tr("Fortune Client"),
+ QMessageBox::information(this, tr("Local Fortune Client"),
tr("The following error occurred: %1.")
.arg(socket->errorString()));
}
diff --git a/examples/corelib/ipc/localfortuneclient/client.h b/examples/corelib/ipc/localfortuneclient/client.h
index 8e628efcee..0c1ede94c9 100644
--- a/examples/corelib/ipc/localfortuneclient/client.h
+++ b/examples/corelib/ipc/localfortuneclient/client.h
@@ -52,11 +52,11 @@
#define CLIENT_H
#include <QDialog>
+#include <QDataStream>
#include <qlocalsocket.h>
QT_BEGIN_NAMESPACE
-class QDialogButtonBox;
class QLabel;
class QLineEdit;
class QPushButton;
@@ -68,7 +68,7 @@ class Client : public QDialog
Q_OBJECT
public:
- Client(QWidget *parent = 0);
+ explicit Client(QWidget *parent = nullptr);
private slots:
void requestNewFortune();
@@ -77,16 +77,15 @@ private slots:
void enableGetFortuneButton();
private:
- QLabel *hostLabel;
QLineEdit *hostLineEdit;
- QLabel *statusLabel;
QPushButton *getFortuneButton;
- QPushButton *quitButton;
- QDialogButtonBox *buttonBox;
+ QLabel *statusLabel;
QLocalSocket *socket;
- QString currentFortune;
+ QDataStream in;
quint32 blockSize;
+
+ QString currentFortune;
};
#endif
diff --git a/examples/corelib/ipc/localfortuneclient/main.cpp b/examples/corelib/ipc/localfortuneclient/main.cpp
index dd13a05be9..ed5cf4c569 100644
--- a/examples/corelib/ipc/localfortuneclient/main.cpp
+++ b/examples/corelib/ipc/localfortuneclient/main.cpp
@@ -55,6 +55,7 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
+ QGuiApplication::setApplicationDisplayName(Client::tr("Local Fortune Client"));
Client client;
client.show();
return app.exec();
diff --git a/examples/corelib/ipc/localfortuneserver/main.cpp b/examples/corelib/ipc/localfortuneserver/main.cpp
index cd066a0acd..6f8ec539fe 100644
--- a/examples/corelib/ipc/localfortuneserver/main.cpp
+++ b/examples/corelib/ipc/localfortuneserver/main.cpp
@@ -58,8 +58,8 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
+ QGuiApplication::setApplicationDisplayName(Server::tr("Local Fortune Server"));
Server server;
server.show();
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
return app.exec();
}
diff --git a/examples/corelib/ipc/localfortuneserver/server.cpp b/examples/corelib/ipc/localfortuneserver/server.cpp
index 2eee4760be..be8d4750d6 100644
--- a/examples/corelib/ipc/localfortuneserver/server.cpp
+++ b/examples/corelib/ipc/localfortuneserver/server.cpp
@@ -60,22 +60,21 @@
Server::Server(QWidget *parent)
: QDialog(parent)
{
- statusLabel = new QLabel;
- statusLabel->setWordWrap(true);
- quitButton = new QPushButton(tr("Quit"));
- quitButton->setAutoDefault(false);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
server = new QLocalServer(this);
if (!server->listen("fortune")) {
- QMessageBox::critical(this, tr("Fortune Server"),
+ QMessageBox::critical(this, tr("Local Fortune Server"),
tr("Unable to start the server: %1.")
.arg(server->errorString()));
close();
return;
}
+ QLabel *statusLabel = new QLabel;
+ statusLabel->setWordWrap(true);
statusLabel->setText(tr("The server is running.\n"
- "Run the Fortune Client example now."));
+ "Run the Local Fortune Client example now."));
fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
<< tr("You've got to think about tomorrow.")
@@ -85,35 +84,36 @@ Server::Server(QWidget *parent)
<< tr("You cannot kill time without injuring eternity.")
<< tr("Computers are not intelligent. They only think they are.");
- connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
- connect(server, SIGNAL(newConnection()), this, SLOT(sendFortune()));
+ QPushButton *quitButton = new QPushButton(tr("Quit"));
+ quitButton->setAutoDefault(false);
+ connect(quitButton, &QPushButton::clicked, this, &Server::close);
+ connect(server, &QLocalServer::newConnection, this, &Server::sendFortune);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
- QVBoxLayout *mainLayout = new QVBoxLayout;
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
- setLayout(mainLayout);
- setWindowTitle(tr("Fortune Server"));
+ setWindowTitle(QGuiApplication::applicationDisplayName());
}
void Server::sendFortune()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
- out.setVersion(QDataStream::Qt_4_0);
- out << (quint32)0;
- out << fortunes.at(qrand() % fortunes.size());
- out.device()->seek(0);
- out << (quint32)(block.size() - sizeof(quint32));
+ out.setVersion(QDataStream::Qt_5_10);
+ const int fortuneIndex = QRandomGenerator::global()->bounded(0, fortunes.size());
+ const QString &message = fortunes.at(fortuneIndex);
+ out << quint32(message.size());
+ out << message;
QLocalSocket *clientConnection = server->nextPendingConnection();
- connect(clientConnection, SIGNAL(disconnected()),
- clientConnection, SLOT(deleteLater()));
+ connect(clientConnection, &QLocalSocket::disconnected,
+ clientConnection, &QLocalSocket::deleteLater);
clientConnection->write(block);
clientConnection->flush();
diff --git a/examples/corelib/ipc/localfortuneserver/server.h b/examples/corelib/ipc/localfortuneserver/server.h
index c77b4e8127..6b90ba5932 100644
--- a/examples/corelib/ipc/localfortuneserver/server.h
+++ b/examples/corelib/ipc/localfortuneserver/server.h
@@ -64,14 +64,12 @@ class Server : public QDialog
Q_OBJECT
public:
- Server(QWidget *parent = 0);
+ explicit Server(QWidget *parent = nullptr);
private slots:
void sendFortune();
private:
- QLabel *statusLabel;
- QPushButton *quitButton;
QLocalServer *server;
QStringList fortunes;
};
diff --git a/examples/corelib/ipc/sharedmemory/sharedmemory.pro b/examples/corelib/ipc/sharedmemory/sharedmemory.pro
index c1b634732e..f236fbce33 100644
--- a/examples/corelib/ipc/sharedmemory/sharedmemory.pro
+++ b/examples/corelib/ipc/sharedmemory/sharedmemory.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
SOURCES += main.cpp \
dialog.cpp
diff --git a/examples/corelib/json/savegame/character.cpp b/examples/corelib/json/savegame/character.cpp
index 20bbc34961..046cde3091 100644
--- a/examples/corelib/json/savegame/character.cpp
+++ b/examples/corelib/json/savegame/character.cpp
@@ -50,12 +50,17 @@
#include "character.h"
+#include <QMetaEnum>
+#include <QTextStream>
+
Character::Character() :
mLevel(0),
mClassType(Warrior) {
}
-Character::Character(const QString &name, int level, Character::ClassType classType) :
+Character::Character(const QString &name,
+ int level,
+ Character::ClassType classType) :
mName(name),
mLevel(level),
mClassType(classType)
@@ -95,9 +100,14 @@ void Character::setClassType(Character::ClassType classType)
//! [0]
void Character::read(const QJsonObject &json)
{
- mName = json["name"].toString();
- mLevel = json["level"].toDouble();
- mClassType = ClassType(qRound(json["classType"].toDouble()));
+ if (json.contains("name") && json["name"].isString())
+ mName = json["name"].toString();
+
+ if (json.contains("level") && json["level"].isDouble())
+ mLevel = json["level"].toInt();
+
+ if (json.contains("classType") && json["classType"].isDouble())
+ mClassType = ClassType(json["classType"].toInt());
}
//! [0]
@@ -109,3 +119,13 @@ void Character::write(QJsonObject &json) const
json["classType"] = mClassType;
}
//! [1]
+
+void Character::print(int indentation) const
+{
+ const QString indent(indentation * 2, ' ');
+ QTextStream(stdout) << indent << "Name:\t" << mName << "\n";
+ QTextStream(stdout) << indent << "Level:\t" << mLevel << "\n";
+
+ QString className = QMetaEnum::fromType<ClassType>().valueToKey(mClassType);
+ QTextStream(stdout) << indent << "Class:\t" << className << "\n";
+}
diff --git a/examples/corelib/json/savegame/character.h b/examples/corelib/json/savegame/character.h
index 740496822c..cbf06d7fd6 100644
--- a/examples/corelib/json/savegame/character.h
+++ b/examples/corelib/json/savegame/character.h
@@ -52,15 +52,19 @@
#define CHARACTER_H
#include <QJsonObject>
+#include <QObject>
#include <QString>
//! [0]
class Character
{
+ Q_GADGET;
+
public:
enum ClassType {
Warrior, Mage, Archer
};
+ Q_ENUM(ClassType)
Character();
Character(const QString &name, int level, ClassType classType);
@@ -76,6 +80,8 @@ public:
void read(const QJsonObject &json);
void write(QJsonObject &json) const;
+
+ void print(int indentation = 0) const;
private:
QString mName;
int mLevel;
diff --git a/examples/corelib/json/savegame/doc/src/savegame.qdoc b/examples/corelib/json/savegame/doc/src/savegame.qdoc
index fec5fe8e5d..06e70680c6 100644
--- a/examples/corelib/json/savegame/doc/src/savegame.qdoc
+++ b/examples/corelib/json/savegame/doc/src/savegame.qdoc
@@ -61,8 +61,8 @@
QJsonObject argument. You can use either \l QJsonObject::operator[]() or
QJsonObject::value() to access values within the JSON object; both are
const functions and return QJsonValue::Undefined if the key is invalid. We
- could check if the keys are valid before attempting to read them with
- QJsonObject::contains(), but we assume that they are.
+ check if the keys are valid before attempting to read them with
+ QJsonObject::contains().
\snippet json/savegame/character.cpp 1
@@ -77,7 +77,7 @@
\snippet json/savegame/level.h 0
We want to have several levels in our game, each with several NPCs, so we
- keep a QList of Character objects. We also provide the familiar read() and
+ keep a QVector of Character objects. We also provide the familiar read() and
write() functions.
\snippet json/savegame/level.cpp 0
@@ -86,7 +86,7 @@
case, we construct a QJsonArray from the value associated with the key
\c "npcs". Then, for each QJsonValue element in the array, we call
toObject() to get the Character's JSON object. The Character object can then
- read their JSON and be appended to our NPC list.
+ read their JSON and be appended to our NPC array.
\note \l{Container Classes}{Associate containers} can be written by storing
the key in each value object (if it's not already). With this approach, the
@@ -120,10 +120,10 @@
\snippet json/savegame/game.cpp 1
The first thing we do in the read() function is tell the player to read
- itself. We then clear the levels list so that calling loadGame() on the same
- Game object twice doesn't result in old levels hanging around.
+ itself. We then clear the level array so that calling loadGame() on the
+ same Game object twice doesn't result in old levels hanging around.
- We then populate the level list by reading each Level from a QJsonArray.
+ We then populate the level array by reading each Level from a QJsonArray.
\snippet json/savegame/game.cpp 2
@@ -159,20 +159,23 @@
Since we're only interested in demonstrating \e serialization of a game with
JSON, our game is not actually playable. Therefore, we only need
- QCoreApplication and have no event loop. We create our game and assume that
- the player had a great time and made lots of progress, altering the internal
- state of our Character, Level and Game objects.
+ QCoreApplication and have no event loop. On application start-up we parse
+ the command-line arguments to decide how to start the game. For the first
+ argument the options "new" (default) and "load" are available. When "new"
+ is specified a new game will be generated, and when "load" is specified a
+ previously saved game will be loaded in. For the second argument
+ "json" (default) and "binary" are available as options. This argument will
+ decide which file is saved to and/or loaded from. We then move ahead and
+ assume that the player had a great time and made lots of progress, altering
+ the internal state of our Character, Level and Game objects.
\snippet json/savegame/main.cpp 1
When the player has finished, we save their game. For demonstration
- purposes, we serialize to both JSON and binary. You can examine the contents
- of the files in the same directory as the executable, although the binary
- save file will contain some garbage characters (which is normal).
-
- To show that the saved files can be loaded again, we call loadGame() for
- each format, returning \c 1 on failure. Assuming everything went well, we
- return \c 0 to indicate success.
+ purposes, we can serialize to either JSON or binary. You can examine the
+ contents of the files in the same directory as the executable (or re-run
+ the example, making sure to also specify the "load" option), although the
+ binary save file will contain some garbage characters (which is normal).
That concludes our example. As you can see, serialization with Qt's JSON
classes is very simple and convenient. The advantages of using QJsonDocument
diff --git a/examples/corelib/json/savegame/game.cpp b/examples/corelib/json/savegame/game.cpp
index b0d800f4ab..4caec71a03 100644
--- a/examples/corelib/json/savegame/game.cpp
+++ b/examples/corelib/json/savegame/game.cpp
@@ -53,41 +53,54 @@
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
+#include <QRandomGenerator>
+#include <QTextStream>
-Game::Game()
-{
-}
-
-const Character &Game::player() const
+Character Game::player() const
{
return mPlayer;
}
-const QList<Level> &Game::levels() const {
+QVector<Level> Game::levels() const
+{
return mLevels;
}
//! [0]
-void Game::newGame() {
+void Game::newGame()
+{
mPlayer = Character();
mPlayer.setName(QStringLiteral("Hero"));
mPlayer.setClassType(Character::Archer);
- mPlayer.setLevel(15);
+ mPlayer.setLevel(QRandomGenerator::global()->bounded(15, 21));
mLevels.clear();
-
- Level village;
- QList<Character> villageNpcs;
- villageNpcs.append(Character(QStringLiteral("Barry the Blacksmith"), 10, Character::Warrior));
- villageNpcs.append(Character(QStringLiteral("Terry the Trader"), 10, Character::Warrior));
+ mLevels.reserve(2);
+
+ Level village(QStringLiteral("Village"));
+ QVector<Character> villageNpcs;
+ villageNpcs.reserve(2);
+ villageNpcs.append(Character(QStringLiteral("Barry the Blacksmith"),
+ QRandomGenerator::global()->bounded(8, 11),
+ Character::Warrior));
+ villageNpcs.append(Character(QStringLiteral("Terry the Trader"),
+ QRandomGenerator::global()->bounded(6, 8),
+ Character::Warrior));
village.setNpcs(villageNpcs);
mLevels.append(village);
- Level dungeon;
- QList<Character> dungeonNpcs;
- dungeonNpcs.append(Character(QStringLiteral("Eric the Evil"), 20, Character::Mage));
- dungeonNpcs.append(Character(QStringLiteral("Eric's Sidekick #1"), 5, Character::Warrior));
- dungeonNpcs.append(Character(QStringLiteral("Eric's Sidekick #2"), 5, Character::Warrior));
+ Level dungeon(QStringLiteral("Dungeon"));
+ QVector<Character> dungeonNpcs;
+ dungeonNpcs.reserve(3);
+ dungeonNpcs.append(Character(QStringLiteral("Eric the Evil"),
+ QRandomGenerator::global()->bounded(18, 26),
+ Character::Mage));
+ dungeonNpcs.append(Character(QStringLiteral("Eric's Left Minion"),
+ QRandomGenerator::global()->bounded(5, 7),
+ Character::Warrior));
+ dungeonNpcs.append(Character(QStringLiteral("Eric's Right Minion"),
+ QRandomGenerator::global()->bounded(4, 9),
+ Character::Warrior));
dungeon.setNpcs(dungeonNpcs);
mLevels.append(dungeon);
}
@@ -113,6 +126,10 @@ bool Game::loadGame(Game::SaveFormat saveFormat)
read(loadDoc.object());
+ QTextStream(stdout) << "Loaded save for "
+ << loadDoc["player"]["name"].toString()
+ << " using "
+ << (saveFormat != Json ? "binary " : "") << "JSON...\n";
return true;
}
//! [3]
@@ -143,15 +160,19 @@ bool Game::saveGame(Game::SaveFormat saveFormat) const
//! [1]
void Game::read(const QJsonObject &json)
{
- mPlayer.read(json["player"].toObject());
-
- mLevels.clear();
- QJsonArray levelArray = json["levels"].toArray();
- for (int levelIndex = 0; levelIndex < levelArray.size(); ++levelIndex) {
- QJsonObject levelObject = levelArray[levelIndex].toObject();
- Level level;
- level.read(levelObject);
- mLevels.append(level);
+ if (json.contains("player") && json["player"].isObject())
+ mPlayer.read(json["player"].toObject());
+
+ if (json.contains("levels") && json["levels"].isArray()) {
+ QJsonArray levelArray = json["levels"].toArray();
+ mLevels.clear();
+ mLevels.reserve(levelArray.size());
+ for (int levelIndex = 0; levelIndex < levelArray.size(); ++levelIndex) {
+ QJsonObject levelObject = levelArray[levelIndex].toObject();
+ Level level;
+ level.read(levelObject);
+ mLevels.append(level);
+ }
}
}
//! [1]
@@ -172,3 +193,14 @@ void Game::write(QJsonObject &json) const
json["levels"] = levelArray;
}
//! [2]
+
+void Game::print(int indentation) const
+{
+ const QString indent(indentation * 2, ' ');
+ QTextStream(stdout) << indent << "Player\n";
+ mPlayer.print(indentation + 1);
+
+ QTextStream(stdout) << indent << "Levels\n";
+ for (Level level : mLevels)
+ level.print(indentation + 1);
+}
diff --git a/examples/corelib/json/savegame/game.h b/examples/corelib/json/savegame/game.h
index c02832b0ab..3da9c148be 100644
--- a/examples/corelib/json/savegame/game.h
+++ b/examples/corelib/json/savegame/game.h
@@ -52,7 +52,7 @@
#define GAME_H
#include <QJsonObject>
-#include <QList>
+#include <QVector>
#include "character.h"
#include "level.h"
@@ -61,14 +61,12 @@
class Game
{
public:
- Game();
-
enum SaveFormat {
Json, Binary
};
- const Character &player() const;
- const QList<Level> &levels() const;
+ Character player() const;
+ QVector<Level> levels() const;
void newGame();
bool loadGame(SaveFormat saveFormat);
@@ -76,9 +74,11 @@ public:
void read(const QJsonObject &json);
void write(QJsonObject &json) const;
+
+ void print(int indentation = 0) const;
private:
Character mPlayer;
- QList<Level> mLevels;
+ QVector<Level> mLevels;
};
//! [0]
diff --git a/examples/corelib/json/savegame/level.cpp b/examples/corelib/json/savegame/level.cpp
index 5b9fb5c90a..8eda107f46 100644
--- a/examples/corelib/json/savegame/level.cpp
+++ b/examples/corelib/json/savegame/level.cpp
@@ -51,16 +51,23 @@
#include "level.h"
#include <QJsonArray>
+#include <QTextStream>
-Level::Level() {
+Level::Level(const QString &name) : mName(name)
+{
}
-const QList<Character> &Level::npcs() const
+QString Level::name() const
+{
+ return mName;
+}
+
+QVector<Character> Level::npcs() const
{
return mNpcs;
}
-void Level::setNpcs(const QList<Character> &npcs)
+void Level::setNpcs(const QVector<Character> &npcs)
{
mNpcs = npcs;
}
@@ -68,13 +75,19 @@ void Level::setNpcs(const QList<Character> &npcs)
//! [0]
void Level::read(const QJsonObject &json)
{
- mNpcs.clear();
- QJsonArray npcArray = json["npcs"].toArray();
- for (int npcIndex = 0; npcIndex < npcArray.size(); ++npcIndex) {
- QJsonObject npcObject = npcArray[npcIndex].toObject();
- Character npc;
- npc.read(npcObject);
- mNpcs.append(npc);
+ if (json.contains("name") && json["name"].isString())
+ mName = json["name"].toString();
+
+ if (json.contains("npcs") && json["npcs"].isArray()) {
+ QJsonArray npcArray = json["npcs"].toArray();
+ mNpcs.clear();
+ mNpcs.reserve(npcArray.size());
+ for (int npcIndex = 0; npcIndex < npcArray.size(); ++npcIndex) {
+ QJsonObject npcObject = npcArray[npcIndex].toObject();
+ Character npc;
+ npc.read(npcObject);
+ mNpcs.append(npc);
+ }
}
}
//! [0]
@@ -82,6 +95,7 @@ void Level::read(const QJsonObject &json)
//! [1]
void Level::write(QJsonObject &json) const
{
+ json["name"] = mName;
QJsonArray npcArray;
foreach (const Character npc, mNpcs) {
QJsonObject npcObject;
@@ -91,3 +105,13 @@ void Level::write(QJsonObject &json) const
json["npcs"] = npcArray;
}
//! [1]
+
+void Level::print(int indentation) const
+{
+ const QString indent(indentation * 2, ' ');
+ QTextStream(stdout) << indent << "Name:\t" << mName << "\n";
+
+ QTextStream(stdout) << indent << "NPCs:\n";
+ for (const Character &character : mNpcs)
+ character.print(2);
+}
diff --git a/examples/corelib/json/savegame/level.h b/examples/corelib/json/savegame/level.h
index 878510e9d5..393524abfd 100644
--- a/examples/corelib/json/savegame/level.h
+++ b/examples/corelib/json/savegame/level.h
@@ -52,7 +52,7 @@
#define LEVEL_H
#include <QJsonObject>
-#include <QList>
+#include <QVector>
#include "character.h"
@@ -60,15 +60,21 @@
class Level
{
public:
- Level();
+ Level() = default;
+ Level(const QString &name);
- const QList<Character> &npcs() const;
- void setNpcs(const QList<Character> &npcs);
+ QString name() const;
+
+ QVector<Character> npcs() const;
+ void setNpcs(const QVector<Character> &npcs);
void read(const QJsonObject &json);
void write(QJsonObject &json) const;
+
+ void print(int indentation = 0) const;
private:
- QList<Character> mNpcs;
+ QString mName;
+ QVector<Character> mNpcs;
};
//! [0]
diff --git a/examples/corelib/json/savegame/main.cpp b/examples/corelib/json/savegame/main.cpp
index 2e4e864942..d091684211 100644
--- a/examples/corelib/json/savegame/main.cpp
+++ b/examples/corelib/json/savegame/main.cpp
@@ -49,30 +49,32 @@
****************************************************************************/
#include <QCoreApplication>
+#include <QTextStream>
#include "game.h"
//! [0]
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
+ QStringList args = QCoreApplication::arguments();
+ bool newGame = true;
+ if (args.length() > 1)
+ newGame = (args[1].toLower() != QStringLiteral("load"));
+ bool json = true;
+ if (args.length() > 2)
+ json = (args[2].toLower() != QStringLiteral("binary"));
Game game;
- game.newGame();
+ if (newGame)
+ game.newGame();
+ else if (!game.loadGame(json ? Game::Json : Game::Binary))
+ return 1;
// Game is played; changes are made...
//! [0]
//! [1]
- if (!game.saveGame(Game::Json))
- return 1;
-
- if (!game.saveGame(Game::Binary))
- return 1;
-
- Game fromJsonGame;
- if (!fromJsonGame.loadGame(Game::Json))
- return 1;
-
- Game fromBinaryGame;
- if (!fromBinaryGame.loadGame(Game::Binary))
+ QTextStream(stdout) << "Game ended in the following state:\n";
+ game.print();
+ if (!game.saveGame(json ? Game::Json : Game::Binary))
return 1;
return 0;
diff --git a/examples/corelib/mimetypes/mimetypebrowser/mimetypebrowser.pro b/examples/corelib/mimetypes/mimetypebrowser/mimetypebrowser.pro
index 806e9cbd14..5f0dd79963 100644
--- a/examples/corelib/mimetypes/mimetypebrowser/mimetypebrowser.pro
+++ b/examples/corelib/mimetypes/mimetypebrowser/mimetypebrowser.pro
@@ -1,5 +1,6 @@
TEMPLATE = app
QT += widgets
+requires(qtConfig(treeview))
CONFIG -= app_bundle
CONFIG += c++11
diff --git a/examples/corelib/threads/queuedcustomtype/main.cpp b/examples/corelib/threads/queuedcustomtype/main.cpp
index 7084b7538a..1f25fafa1b 100644
--- a/examples/corelib/threads/queuedcustomtype/main.cpp
+++ b/examples/corelib/threads/queuedcustomtype/main.cpp
@@ -126,7 +126,6 @@ int main(int argc, char *argv[])
//! [main start] //! [register meta-type for queued communications]
qRegisterMetaType<Block>();
//! [register meta-type for queued communications]
- qsrand(QTime::currentTime().elapsed());
Window window;
window.show();
diff --git a/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro b/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro
index 8b91fb9ac7..95a7a81526 100644
--- a/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro
+++ b/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro
@@ -6,6 +6,7 @@ SOURCES = main.cpp \
renderthread.cpp \
window.cpp
QT += widgets
+requires(qtConfig(filedialog))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/queuedcustomtype
diff --git a/examples/corelib/threads/queuedcustomtype/renderthread.cpp b/examples/corelib/threads/queuedcustomtype/renderthread.cpp
index f894dd587f..67cedf1e74 100644
--- a/examples/corelib/threads/queuedcustomtype/renderthread.cpp
+++ b/examples/corelib/threads/queuedcustomtype/renderthread.cpp
@@ -50,6 +50,8 @@
#include "renderthread.h"
+#include <QRandomGenerator>
+
RenderThread::RenderThread(QObject *parent)
: QThread(parent)
{
@@ -82,9 +84,9 @@ void RenderThread::run()
for (int s = size; s > 0; --s) {
for (int c = 0; c < 400; ++c) {
//![processing the image (start)]
- int x1 = qMax(0, (qrand() % m_image.width()) - s/2);
+ int x1 = qMax(0, QRandomGenerator::global()->bounded(m_image.width()) - s/2);
int x2 = qMin(x1 + s/2 + 1, m_image.width());
- int y1 = qMax(0, (qrand() % m_image.height()) - s/2);
+ int y1 = qMax(0, QRandomGenerator::global()->bounded(m_image.height()) - s/2);
int y2 = qMin(y1 + s/2 + 1, m_image.height());
int n = 0;
int red = 0;
diff --git a/examples/corelib/threads/semaphores/semaphores.cpp b/examples/corelib/threads/semaphores/semaphores.cpp
index 37dd4cda20..145624bb0b 100644
--- a/examples/corelib/threads/semaphores/semaphores.cpp
+++ b/examples/corelib/threads/semaphores/semaphores.cpp
@@ -70,10 +70,9 @@ class Producer : public QThread
public:
void run() override
{
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
for (int i = 0; i < DataSize; ++i) {
freeBytes.acquire();
- buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
+ buffer[i % BufferSize] = "ACGT"[QRandomGenerator::global()->bounded(4)];
usedBytes.release();
}
}
diff --git a/examples/corelib/threads/waitconditions/waitconditions.cpp b/examples/corelib/threads/waitconditions/waitconditions.cpp
index 9eab28f94c..963ee03a76 100644
--- a/examples/corelib/threads/waitconditions/waitconditions.cpp
+++ b/examples/corelib/threads/waitconditions/waitconditions.cpp
@@ -76,15 +76,13 @@ public:
void run() override
{
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
-
for (int i = 0; i < DataSize; ++i) {
mutex.lock();
if (numUsedBytes == BufferSize)
bufferNotFull.wait(&mutex);
mutex.unlock();
- buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
+ buffer[i % BufferSize] = "ACGT"[QRandomGenerator::global()->bounded(4)];
mutex.lock();
++numUsedBytes;
diff --git a/examples/corelib/tools/contiguouscache/contiguouscache.pro b/examples/corelib/tools/contiguouscache/contiguouscache.pro
index fb2267fc64..304581356a 100644
--- a/examples/corelib/tools/contiguouscache/contiguouscache.pro
+++ b/examples/corelib/tools/contiguouscache/contiguouscache.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(listview))
HEADERS = randomlistmodel.h
SOURCES = randomlistmodel.cpp \
diff --git a/examples/corelib/tools/contiguouscache/randomlistmodel.cpp b/examples/corelib/tools/contiguouscache/randomlistmodel.cpp
index f3d8f4b133..ccaa45a28b 100644
--- a/examples/corelib/tools/contiguouscache/randomlistmodel.cpp
+++ b/examples/corelib/tools/contiguouscache/randomlistmodel.cpp
@@ -48,6 +48,7 @@
**
****************************************************************************/
#include "randomlistmodel.h"
+#include <QRandomGenerator>
#include <stdlib.h>
static const int bufferSize(500);
@@ -101,6 +102,6 @@ void RandomListModel::cacheRows(int from, int to) const
//![1]
QString RandomListModel::fetchRow(int position) const
{
- return QString::number(rand() % ++position);
+ return QString::number(QRandomGenerator::global()->bounded(++position));
}
//![1]
diff --git a/examples/dbus/remotecontrolledcar/car/car.cpp b/examples/dbus/remotecontrolledcar/car/car.cpp
index 67daac79ba..2de4e6447a 100644
--- a/examples/dbus/remotecontrolledcar/car/car.cpp
+++ b/examples/dbus/remotecontrolledcar/car/car.cpp
@@ -50,9 +50,7 @@
#include "car.h"
#include <QtWidgets/QtWidgets>
-#include <math.h>
-
-static const double Pi = 3.14159265358979323846264338327950288419717;
+#include <qmath.h>
QRectF Car::boundingRect() const
{
@@ -135,10 +133,10 @@ void Car::timerEvent(QTimerEvent *event)
Q_UNUSED(event);
const qreal axelDistance = 54;
- qreal wheelsAngleRads = (wheelsAngle * Pi) / 180;
+ qreal wheelsAngleRads = qDegreesToRadians(wheelsAngle);
qreal turnDistance = ::cos(wheelsAngleRads) * axelDistance * 2;
qreal turnRateRads = wheelsAngleRads / turnDistance; // rough estimate
- qreal turnRate = (turnRateRads * 180) / Pi;
+ qreal turnRate = qRadiansToDegrees(turnRateRads);
qreal rotation = speed * turnRate;
setTransform(QTransform().rotate(rotation), true);
diff --git a/examples/embedded/flickable/main.cpp b/examples/embedded/flickable/main.cpp
index 9772ba4f55..9367c8b4fe 100644
--- a/examples/embedded/flickable/main.cpp
+++ b/examples/embedded/flickable/main.cpp
@@ -72,7 +72,7 @@ static QStringList colorPairs(int max)
// randomize it
colors.clear();
while (combinedColors.count()) {
- int i = qrand() % combinedColors.count();
+ int i = QRandomGenerator::global()->bounded(combinedColors.count());
colors << combinedColors[i];
combinedColors.removeAt(i);
if (colors.count() == max)
diff --git a/examples/embedded/lightmaps/lightmaps.cpp b/examples/embedded/lightmaps/lightmaps.cpp
index a8bc13beaf..6334530c3a 100644
--- a/examples/embedded/lightmaps/lightmaps.cpp
+++ b/examples/embedded/lightmaps/lightmaps.cpp
@@ -52,15 +52,9 @@
#include <QtWidgets>
#include <QtNetwork>
-#include <math.h>
-
#include "lightmaps.h"
#include "slippymap.h"
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
// how long (milliseconds) the user need to hold (after a tap on the screen)
// before triggering the magnifying glass feature
// 701, a prime number, is the sum of 229, 233, 239
diff --git a/examples/embedded/lightmaps/slippymap.cpp b/examples/embedded/lightmaps/slippymap.cpp
index 7e847c2501..ff43261700 100644
--- a/examples/embedded/lightmaps/slippymap.cpp
+++ b/examples/embedded/lightmaps/slippymap.cpp
@@ -48,15 +48,10 @@
**
****************************************************************************/
-#include <math.h>
-
#include <QtWidgets>
#include <QtNetwork>
#include "slippymap.h"
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include "qmath.h"
uint qHash(const QPoint& p)
{
@@ -68,10 +63,10 @@ const int tdim = 256;
QPointF tileForCoordinate(qreal lat, qreal lng, int zoom)
{
+ qreal radianLat = qDegreesToRadians(lat);
qreal zn = static_cast<qreal>(1 << zoom);
qreal tx = (lng + 180.0) / 360.0;
- qreal ty = (1.0 - log(tan(lat * M_PI / 180.0) +
- 1.0 / cos(lat * M_PI / 180.0)) / M_PI) / 2.0;
+ qreal ty = 0.5 - log(tan(radianLat) + 1.0 / cos(radianLat)) / M_PI / 2.0;
return QPointF(tx * zn, ty * zn);
}
@@ -86,8 +81,7 @@ qreal latitudeFromTile(qreal ty, int zoom)
{
qreal zn = static_cast<qreal>(1 << zoom);
qreal n = M_PI - 2 * M_PI * ty / zn;
- qreal lng = 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n)));
- return lng;
+ return qRadiansToDegrees(atan(sinh(n)));
}
diff --git a/examples/embedded/raycasting/raycasting.cpp b/examples/embedded/raycasting/raycasting.cpp
index 992c383db1..d37b9f5d2e 100644
--- a/examples/embedded/raycasting/raycasting.cpp
+++ b/examples/embedded/raycasting/raycasting.cpp
@@ -50,12 +50,7 @@
#include <QtCore>
#include <QtWidgets>
-
-#include <math.h>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include <qmath.h>
#define WORLD_SIZE 8
int world_map[WORLD_SIZE][WORLD_SIZE] = {
diff --git a/examples/examples.pro b/examples/examples.pro
index d87fa2da88..4ec5ca60e2 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -14,8 +14,11 @@ qtHaveModule(concurrent): SUBDIRS += qtconcurrent
qtHaveModule(sql): SUBDIRS += sql
qtHaveModule(widgets): SUBDIRS += widgets
qtHaveModule(xml): SUBDIRS += xml
-qtHaveModule(gui): SUBDIRS += gui
-qtHaveModule(gui):qtConfig(opengl): SUBDIRS += opengl
+qtHaveModule(gui) {
+ SUBDIRS += gui
+ qtConfig(opengl): SUBDIRS += opengl
+ qtConfig(vulkan): SUBDIRS += vulkan
+}
aggregate.files = aggregate/examples.pro
aggregate.path = $$[QT_INSTALL_EXAMPLES]
diff --git a/examples/gui/rasterwindow/rasterwindow.cpp b/examples/gui/rasterwindow/rasterwindow.cpp
index 68d1d7f524..3eacd20145 100644
--- a/examples/gui/rasterwindow/rasterwindow.cpp
+++ b/examples/gui/rasterwindow/rasterwindow.cpp
@@ -111,6 +111,7 @@ void RasterWindow::renderNow()
painter.fillRect(0, 0, width(), height(), Qt::white);
render(&painter);
+ painter.end();
m_backingStore->endPaint();
m_backingStore->flush(rect);
diff --git a/examples/network/bearermonitor/bearermonitor.pro b/examples/network/bearermonitor/bearermonitor.pro
index d75e021834..7d90b408e0 100644
--- a/examples/network/bearermonitor/bearermonitor.pro
+++ b/examples/network/bearermonitor/bearermonitor.pro
@@ -1,5 +1,6 @@
TARGET = bearermonitor
QT = core gui network widgets
+requires(qtConfig(treeview))
HEADERS = sessionwidget.h \
bearermonitor.h
diff --git a/examples/network/broadcastreceiver/broadcastreceiver.pro b/examples/network/broadcastreceiver/broadcastreceiver.pro
index edadf1c28d..5c58962f3a 100644
--- a/examples/network/broadcastreceiver/broadcastreceiver.pro
+++ b/examples/network/broadcastreceiver/broadcastreceiver.pro
@@ -1,4 +1,5 @@
QT += network widgets
+requires(qtConfig(udpsocket))
HEADERS = receiver.h
SOURCES = receiver.cpp \
diff --git a/examples/network/broadcastreceiver/receiver.cpp b/examples/network/broadcastreceiver/receiver.cpp
index 4225a19746..2f111b4795 100644
--- a/examples/network/broadcastreceiver/receiver.cpp
+++ b/examples/network/broadcastreceiver/receiver.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -59,7 +59,7 @@ Receiver::Receiver(QWidget *parent)
statusLabel = new QLabel(tr("Listening for broadcasted messages"));
statusLabel->setWordWrap(true);
- quitButton = new QPushButton(tr("&Quit"));
+ auto quitButton = new QPushButton(tr("&Quit"));
//! [0]
udpSocket = new QUdpSocket(this);
@@ -72,12 +72,12 @@ Receiver::Receiver(QWidget *parent)
//! [1]
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
- QHBoxLayout *buttonLayout = new QHBoxLayout;
+ auto buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
- QVBoxLayout *mainLayout = new QVBoxLayout;
+ auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
@@ -87,13 +87,13 @@ Receiver::Receiver(QWidget *parent)
void Receiver::processPendingDatagrams()
{
+ QByteArray datagram;
//! [2]
while (udpSocket->hasPendingDatagrams()) {
- QByteArray datagram;
- datagram.resize(udpSocket->pendingDatagramSize());
+ datagram.resize(int(udpSocket->pendingDatagramSize()));
udpSocket->readDatagram(datagram.data(), datagram.size());
statusLabel->setText(tr("Received datagram: \"%1\"")
- .arg(datagram.data()));
+ .arg(datagram.constData()));
}
//! [2]
}
diff --git a/examples/network/broadcastreceiver/receiver.h b/examples/network/broadcastreceiver/receiver.h
index 71b91246fc..e6f8d97c23 100644
--- a/examples/network/broadcastreceiver/receiver.h
+++ b/examples/network/broadcastreceiver/receiver.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -55,9 +55,7 @@
QT_BEGIN_NAMESPACE
class QLabel;
-class QPushButton;
class QUdpSocket;
-class QAction;
QT_END_NAMESPACE
class Receiver : public QWidget
@@ -65,15 +63,14 @@ class Receiver : public QWidget
Q_OBJECT
public:
- Receiver(QWidget *parent = 0);
+ explicit Receiver(QWidget *parent = nullptr);
private slots:
void processPendingDatagrams();
private:
- QLabel *statusLabel;
- QPushButton *quitButton;
- QUdpSocket *udpSocket;
+ QLabel *statusLabel = nullptr;
+ QUdpSocket *udpSocket = nullptr;
};
#endif
diff --git a/examples/network/broadcastsender/broadcastsender.pro b/examples/network/broadcastsender/broadcastsender.pro
index 4c5af7f849..9598a2e428 100644
--- a/examples/network/broadcastsender/broadcastsender.pro
+++ b/examples/network/broadcastsender/broadcastsender.pro
@@ -1,4 +1,5 @@
QT += network widgets
+requires(qtConfig(udpsocket))
HEADERS = sender.h
SOURCES = sender.cpp \
diff --git a/examples/network/broadcastsender/sender.cpp b/examples/network/broadcastsender/sender.cpp
index 344f898683..ee4896e9dd 100644
--- a/examples/network/broadcastsender/sender.cpp
+++ b/examples/network/broadcastsender/sender.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -50,6 +50,7 @@
#include <QtWidgets>
#include <QtNetwork>
+#include <QtCore>
#include "sender.h"
@@ -60,23 +61,21 @@ Sender::Sender(QWidget *parent)
statusLabel->setWordWrap(true);
startButton = new QPushButton(tr("&Start"));
- quitButton = new QPushButton(tr("&Quit"));
+ auto quitButton = new QPushButton(tr("&Quit"));
- buttonBox = new QDialogButtonBox;
+ auto buttonBox = new QDialogButtonBox;
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
- timer = new QTimer(this);
//! [0]
udpSocket = new QUdpSocket(this);
//! [0]
- messageNo = 1;
- connect(startButton, SIGNAL(clicked()), this, SLOT(startBroadcasting()));
- connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
- connect(timer, SIGNAL(timeout()), this, SLOT(broadcastDatagram()));
+ connect(startButton, &QPushButton::clicked, this, &Sender::startBroadcasting);
+ connect(quitButton, &QPushButton::clicked, this, &Sender::close);
+ connect(&timer, &QTimer::timeout, this, &Sender::broadcastDatagram);
- QVBoxLayout *mainLayout = new QVBoxLayout;
+ auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
@@ -87,7 +86,7 @@ Sender::Sender(QWidget *parent)
void Sender::startBroadcasting()
{
startButton->setEnabled(false);
- timer->start(1000);
+ timer.start(1000);
}
void Sender::broadcastDatagram()
@@ -95,8 +94,7 @@ void Sender::broadcastDatagram()
statusLabel->setText(tr("Now broadcasting datagram %1").arg(messageNo));
//! [1]
QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo);
- udpSocket->writeDatagram(datagram.data(), datagram.size(),
- QHostAddress::Broadcast, 45454);
+ udpSocket->writeDatagram(datagram, QHostAddress::Broadcast, 45454);
//! [1]
++messageNo;
}
diff --git a/examples/network/broadcastsender/sender.h b/examples/network/broadcastsender/sender.h
index e9c1076dd3..f91c7769ec 100644
--- a/examples/network/broadcastsender/sender.h
+++ b/examples/network/broadcastsender/sender.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -52,12 +52,11 @@
#define SENDER_H
#include <QWidget>
+#include <QTimer>
QT_BEGIN_NAMESPACE
-class QDialogButtonBox;
class QLabel;
class QPushButton;
-class QTimer;
class QUdpSocket;
QT_END_NAMESPACE
@@ -66,20 +65,18 @@ class Sender : public QWidget
Q_OBJECT
public:
- Sender(QWidget *parent = 0);
+ explicit Sender(QWidget *parent = nullptr);
private slots:
void startBroadcasting();
void broadcastDatagram();
private:
- QLabel *statusLabel;
- QPushButton *startButton;
- QPushButton *quitButton;
- QDialogButtonBox *buttonBox;
- QUdpSocket *udpSocket;
- QTimer *timer;
- int messageNo;
+ QLabel *statusLabel = nullptr;
+ QPushButton *startButton = nullptr;
+ QUdpSocket *udpSocket = nullptr;
+ QTimer timer;
+ int messageNo = 1;
};
#endif
diff --git a/examples/network/doc/images/http-example.png b/examples/network/doc/images/http-example.png
index 16b0539b1b..c5f3ef1649 100644
--- a/examples/network/doc/images/http-example.png
+++ b/examples/network/doc/images/http-example.png
Binary files differ
diff --git a/examples/network/download/main.cpp b/examples/network/download/main.cpp
index e5ad050de3..96111983ea 100644
--- a/examples/network/download/main.cpp
+++ b/examples/network/download/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,37 +48,29 @@
**
****************************************************************************/
-#include <QCoreApplication>
-#include <QFile>
-#include <QFileInfo>
-#include <QList>
-#include <QNetworkAccessManager>
-#include <QNetworkRequest>
-#include <QNetworkReply>
-#include <QSslError>
-#include <QStringList>
-#include <QTimer>
-#include <QUrl>
+#include <QtCore>
+#include <QtNetwork>
-#include <stdio.h>
+#include <cstdio>
QT_BEGIN_NAMESPACE
class QSslError;
QT_END_NAMESPACE
-QT_USE_NAMESPACE
+using namespace std;
class DownloadManager: public QObject
{
Q_OBJECT
QNetworkAccessManager manager;
- QList<QNetworkReply *> currentDownloads;
+ QVector<QNetworkReply *> currentDownloads;
public:
DownloadManager();
void doDownload(const QUrl &url);
- QString saveFileName(const QUrl &url);
+ static QString saveFileName(const QUrl &url);
bool saveToDisk(const QString &filename, QIODevice *data);
+ static bool isHttpRedirect(QNetworkReply *reply);
public slots:
void execute();
@@ -97,8 +89,9 @@ void DownloadManager::doDownload(const QUrl &url)
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
-#ifndef QT_NO_SSL
- connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(sslErrors(QList<QSslError>)));
+#if QT_CONFIG(ssl)
+ connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
+ SLOT(sslErrors(QList<QSslError>)));
#endif
currentDownloads.append(reply);
@@ -141,6 +134,13 @@ bool DownloadManager::saveToDisk(const QString &filename, QIODevice *data)
return true;
}
+bool DownloadManager::isHttpRedirect(QNetworkReply *reply)
+{
+ int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ return statusCode == 301 || statusCode == 302 || statusCode == 303
+ || statusCode == 305 || statusCode == 307 || statusCode == 308;
+}
+
void DownloadManager::execute()
{
QStringList args = QCoreApplication::instance()->arguments();
@@ -156,7 +156,7 @@ void DownloadManager::execute()
return;
}
- foreach (QString arg, args) {
+ for (const QString &arg : qAsConst(args)) {
QUrl url = QUrl::fromEncoded(arg.toLocal8Bit());
doDownload(url);
}
@@ -164,8 +164,8 @@ void DownloadManager::execute()
void DownloadManager::sslErrors(const QList<QSslError> &sslErrors)
{
-#ifndef QT_NO_SSL
- foreach (const QSslError &error, sslErrors)
+#if QT_CONFIG(ssl)
+ for (const QSslError &error : sslErrors)
fprintf(stderr, "SSL error: %s\n", qPrintable(error.errorString()));
#else
Q_UNUSED(sslErrors);
@@ -180,18 +180,24 @@ void DownloadManager::downloadFinished(QNetworkReply *reply)
url.toEncoded().constData(),
qPrintable(reply->errorString()));
} else {
- QString filename = saveFileName(url);
- if (saveToDisk(filename, reply))
- printf("Download of %s succeeded (saved to %s)\n",
- url.toEncoded().constData(), qPrintable(filename));
+ if (isHttpRedirect(reply)) {
+ fputs("Request was redirected.\n", stderr);
+ } else {
+ QString filename = saveFileName(url);
+ if (saveToDisk(filename, reply)) {
+ printf("Download of %s succeeded (saved to %s)\n",
+ url.toEncoded().constData(), qPrintable(filename));
+ }
+ }
}
currentDownloads.removeAll(reply);
reply->deleteLater();
- if (currentDownloads.isEmpty())
+ if (currentDownloads.isEmpty()) {
// all downloads finished
QCoreApplication::instance()->quit();
+ }
}
int main(int argc, char **argv)
diff --git a/examples/network/downloadmanager/downloadmanager.cpp b/examples/network/downloadmanager/downloadmanager.cpp
index 69d8fd1ebc..e820b4ff70 100644
--- a/examples/network/downloadmanager/downloadmanager.cpp
+++ b/examples/network/downloadmanager/downloadmanager.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -50,23 +50,21 @@
#include "downloadmanager.h"
-#include <QFileInfo>
-#include <QNetworkRequest>
-#include <QNetworkReply>
-#include <QString>
-#include <QStringList>
-#include <QTimer>
-#include <stdio.h>
+#include <QTextStream>
+
+#include <cstdio>
+
+using namespace std;
DownloadManager::DownloadManager(QObject *parent)
- : QObject(parent), downloadedCount(0), totalCount(0)
+ : QObject(parent)
{
}
-void DownloadManager::append(const QStringList &urlList)
+void DownloadManager::append(const QStringList &urls)
{
- foreach (QString url, urlList)
- append(QUrl::fromEncoded(url.toLocal8Bit()));
+ for (const QString &urlAsString : urls)
+ append(QUrl::fromEncoded(urlAsString.toLocal8Bit()));
if (downloadQueue.isEmpty())
QTimer::singleShot(0, this, SIGNAL(finished()));
@@ -167,9 +165,16 @@ void DownloadManager::downloadFinished()
if (currentDownload->error()) {
// download failed
fprintf(stderr, "Failed: %s\n", qPrintable(currentDownload->errorString()));
+ output.remove();
} else {
- printf("Succeeded.\n");
- ++downloadedCount;
+ // let's check if it was actually a redirect
+ if (isHttpRedirect()) {
+ reportRedirect();
+ output.remove();
+ } else {
+ printf("Succeeded.\n");
+ ++downloadedCount;
+ }
}
currentDownload->deleteLater();
@@ -180,3 +185,28 @@ void DownloadManager::downloadReadyRead()
{
output.write(currentDownload->readAll());
}
+
+bool DownloadManager::isHttpRedirect() const
+{
+ int statusCode = currentDownload->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ return statusCode == 301 || statusCode == 302 || statusCode == 303
+ || statusCode == 305 || statusCode == 307 || statusCode == 308;
+}
+
+void DownloadManager::reportRedirect()
+{
+ int statusCode = currentDownload->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ QUrl requestUrl = currentDownload->request().url();
+ QTextStream(stderr) << "Request: " << requestUrl.toDisplayString()
+ << " was redirected with code: " << statusCode
+ << '\n';
+
+ QVariant target = currentDownload->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (!target.isValid())
+ return;
+ QUrl redirectUrl = target.toUrl();
+ if (redirectUrl.isRelative())
+ redirectUrl = requestUrl.resolved(redirectUrl);
+ QTextStream(stderr) << "Redirected to: " << redirectUrl.toDisplayString()
+ << '\n';
+}
diff --git a/examples/network/downloadmanager/downloadmanager.h b/examples/network/downloadmanager/downloadmanager.h
index 550a197ef8..4bc6351ff9 100644
--- a/examples/network/downloadmanager/downloadmanager.h
+++ b/examples/network/downloadmanager/downloadmanager.h
@@ -51,12 +51,8 @@
#ifndef DOWNLOADMANAGER_H
#define DOWNLOADMANAGER_H
-#include <QFile>
-#include <QObject>
-#include <QQueue>
-#include <QTime>
-#include <QUrl>
-#include <QNetworkAccessManager>
+#include <QtNetwork>
+#include <QtCore>
#include "textprogressbar.h"
@@ -64,11 +60,11 @@ class DownloadManager: public QObject
{
Q_OBJECT
public:
- DownloadManager(QObject *parent = 0);
+ explicit DownloadManager(QObject *parent = nullptr);
void append(const QUrl &url);
- void append(const QStringList &urlList);
- QString saveFileName(const QUrl &url);
+ void append(const QStringList &urls);
+ static QString saveFileName(const QUrl &url);
signals:
void finished();
@@ -80,15 +76,18 @@ private slots:
void downloadReadyRead();
private:
+ bool isHttpRedirect() const;
+ void reportRedirect();
+
QNetworkAccessManager manager;
QQueue<QUrl> downloadQueue;
- QNetworkReply *currentDownload;
+ QNetworkReply *currentDownload = nullptr;
QFile output;
QTime downloadTime;
TextProgressBar progressBar;
- int downloadedCount;
- int totalCount;
+ int downloadedCount = 0;
+ int totalCount = 0;
};
#endif
diff --git a/examples/network/downloadmanager/main.cpp b/examples/network/downloadmanager/main.cpp
index 158f04c9e6..e3ba490992 100644
--- a/examples/network/downloadmanager/main.cpp
+++ b/examples/network/downloadmanager/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -50,11 +50,15 @@
#include <QCoreApplication>
#include <QStringList>
+
#include "downloadmanager.h"
-#include <stdio.h>
+
+#include <cstdio>
int main(int argc, char **argv)
{
+ using namespace std;
+
QCoreApplication app(argc, argv);
QStringList arguments = app.arguments();
arguments.takeFirst(); // remove the first argument, which is the program's name
diff --git a/examples/network/downloadmanager/textprogressbar.cpp b/examples/network/downloadmanager/textprogressbar.cpp
index d9506a563a..3449e6bad5 100644
--- a/examples/network/downloadmanager/textprogressbar.cpp
+++ b/examples/network/downloadmanager/textprogressbar.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -49,22 +49,21 @@
****************************************************************************/
#include "textprogressbar.h"
+
#include <QByteArray>
-#include <stdio.h>
-TextProgressBar::TextProgressBar()
- : value(0), maximum(-1), iteration(0)
-{
-}
+#include <cstdio>
+
+using namespace std;
void TextProgressBar::clear()
{
printf("\n");
fflush(stdout);
- iteration = 0;
value = 0;
maximum = -1;
+ iteration = 0;
}
void TextProgressBar::update()
diff --git a/examples/network/downloadmanager/textprogressbar.h b/examples/network/downloadmanager/textprogressbar.h
index 57bcd6e92a..30affeb55c 100644
--- a/examples/network/downloadmanager/textprogressbar.h
+++ b/examples/network/downloadmanager/textprogressbar.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -56,8 +56,6 @@
class TextProgressBar
{
public:
- TextProgressBar();
-
void clear();
void update();
void setMessage(const QString &message);
@@ -65,9 +63,9 @@ public:
private:
QString message;
- qint64 value;
- qint64 maximum;
- int iteration;
+ qint64 value = 0;
+ qint64 maximum = -1;
+ int iteration = 0;
};
#endif
diff --git a/examples/network/fortuneclient/client.cpp b/examples/network/fortuneclient/client.cpp
index c0043e246f..4d3a318a7b 100644
--- a/examples/network/fortuneclient/client.cpp
+++ b/examples/network/fortuneclient/client.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -60,7 +60,6 @@ Client::Client(QWidget *parent)
, portLineEdit(new QLineEdit)
, getFortuneButton(new QPushButton(tr("Get Fortune")))
, tcpSocket(new QTcpSocket(this))
- , networkSession(Q_NULLPTR)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
//! [0]
@@ -90,9 +89,9 @@ Client::Client(QWidget *parent)
portLineEdit->setValidator(new QIntValidator(1, 65535, this));
- QLabel *hostLabel = new QLabel(tr("&Server name:"));
+ auto hostLabel = new QLabel(tr("&Server name:"));
hostLabel->setBuddy(hostCombo);
- QLabel *portLabel = new QLabel(tr("S&erver port:"));
+ auto portLabel = new QLabel(tr("S&erver port:"));
portLabel->setBuddy(portLineEdit);
statusLabel = new QLabel(tr("This examples requires that you run the "
@@ -101,9 +100,9 @@ Client::Client(QWidget *parent)
getFortuneButton->setDefault(true);
getFortuneButton->setEnabled(false);
- QPushButton *quitButton = new QPushButton(tr("Quit"));
+ auto quitButton = new QPushButton(tr("Quit"));
- QDialogButtonBox *buttonBox = new QDialogButtonBox;
+ auto buttonBox = new QDialogButtonBox;
buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
@@ -127,13 +126,13 @@ Client::Client(QWidget *parent)
this, &Client::displayError);
//! [4]
- QGridLayout *mainLayout = Q_NULLPTR;
+ QGridLayout *mainLayout = nullptr;
if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
- QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this);
+ auto outerVerticalLayout = new QVBoxLayout(this);
outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
- QHBoxLayout *outerHorizontalLayout = new QHBoxLayout;
+ auto outerHorizontalLayout = new QHBoxLayout;
outerHorizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
- QGroupBox *groupBox = new QGroupBox(QGuiApplication::applicationDisplayName());
+ auto groupBox = new QGroupBox(QGuiApplication::applicationDisplayName());
mainLayout = new QGridLayout(groupBox);
outerHorizontalLayout->addWidget(groupBox);
outerHorizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
diff --git a/examples/network/fortuneclient/client.h b/examples/network/fortuneclient/client.h
index 8037e9b047..ac335acb83 100644
--- a/examples/network/fortuneclient/client.h
+++ b/examples/network/fortuneclient/client.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -51,9 +51,9 @@
#ifndef CLIENT_H
#define CLIENT_H
+#include <QDataStream>
#include <QDialog>
#include <QTcpSocket>
-#include <QDataStream>
QT_BEGIN_NAMESPACE
class QComboBox;
@@ -70,7 +70,7 @@ class Client : public QDialog
Q_OBJECT
public:
- explicit Client(QWidget *parent = Q_NULLPTR);
+ explicit Client(QWidget *parent = nullptr);
private slots:
void requestNewFortune();
@@ -80,16 +80,16 @@ private slots:
void sessionOpened();
private:
- QComboBox *hostCombo;
- QLineEdit *portLineEdit;
- QLabel *statusLabel;
- QPushButton *getFortuneButton;
+ QComboBox *hostCombo = nullptr;
+ QLineEdit *portLineEdit = nullptr;
+ QLabel *statusLabel = nullptr;
+ QPushButton *getFortuneButton = nullptr;
- QTcpSocket *tcpSocket;
+ QTcpSocket *tcpSocket = nullptr;
QDataStream in;
QString currentFortune;
- QNetworkSession *networkSession;
+ QNetworkSession *networkSession = nullptr;
};
//! [0]
diff --git a/examples/network/fortuneclient/fortuneclient.pro b/examples/network/fortuneclient/fortuneclient.pro
index 8b376d9c53..6cf04a8b62 100644
--- a/examples/network/fortuneclient/fortuneclient.pro
+++ b/examples/network/fortuneclient/fortuneclient.pro
@@ -1,4 +1,5 @@
QT += network widgets
+requires(qtConfig(combobox))
HEADERS = client.h
SOURCES = client.cpp \
diff --git a/examples/network/fortuneclient/main.cpp b/examples/network/fortuneclient/main.cpp
index e313b251ef..6b02708ce1 100644
--- a/examples/network/fortuneclient/main.cpp
+++ b/examples/network/fortuneclient/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -54,7 +54,7 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- QGuiApplication::setApplicationDisplayName(Client::tr("Fortune Client"));
+ QApplication::setApplicationDisplayName(Client::tr("Fortune Client"));
Client client;
client.show();
return app.exec();
diff --git a/examples/network/fortuneserver/main.cpp b/examples/network/fortuneserver/main.cpp
index 12137d647c..a64fcb26dc 100644
--- a/examples/network/fortuneserver/main.cpp
+++ b/examples/network/fortuneserver/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -49,18 +49,14 @@
****************************************************************************/
#include <QApplication>
-#include <QtCore>
-
-#include <stdlib.h>
#include "server.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- QGuiApplication::setApplicationDisplayName(Server::tr("Fortune Server"));
+ QApplication::setApplicationDisplayName(Server::tr("Fortune Server"));
Server server;
server.show();
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
return app.exec();
}
diff --git a/examples/network/fortuneserver/server.cpp b/examples/network/fortuneserver/server.cpp
index f027d68dd9..7db81fe07a 100644
--- a/examples/network/fortuneserver/server.cpp
+++ b/examples/network/fortuneserver/server.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -50,16 +50,13 @@
#include <QtWidgets>
#include <QtNetwork>
-
-#include <stdlib.h>
+#include <QtCore>
#include "server.h"
Server::Server(QWidget *parent)
: QDialog(parent)
, statusLabel(new QLabel)
- , tcpServer(Q_NULLPTR)
- , networkSession(0)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
statusLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
@@ -89,46 +86,46 @@ Server::Server(QWidget *parent)
}
//! [2]
- fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
- << tr("You've got to think about tomorrow.")
- << tr("You will be surprised by a loud noise.")
- << tr("You will feel hungry again in another hour.")
- << tr("You might have mail.")
- << tr("You cannot kill time without injuring eternity.")
- << tr("Computers are not intelligent. They only think they are.");
+ fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
+ << tr("You've got to think about tomorrow.")
+ << tr("You will be surprised by a loud noise.")
+ << tr("You will feel hungry again in another hour.")
+ << tr("You might have mail.")
+ << tr("You cannot kill time without injuring eternity.")
+ << tr("Computers are not intelligent. They only think they are.");
//! [2]
- QPushButton *quitButton = new QPushButton(tr("Quit"));
- quitButton->setAutoDefault(false);
- connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close);
+ auto quitButton = new QPushButton(tr("Quit"));
+ quitButton->setAutoDefault(false);
+ connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close);
//! [3]
- connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune);
+ connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune);
//! [3]
- QHBoxLayout *buttonLayout = new QHBoxLayout;
- buttonLayout->addStretch(1);
- buttonLayout->addWidget(quitButton);
- buttonLayout->addStretch(1);
-
- QVBoxLayout *mainLayout = Q_NULLPTR;
- if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
- QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this);
- outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
- QHBoxLayout *outerHorizontalLayout = new QHBoxLayout;
- outerHorizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
- QGroupBox *groupBox = new QGroupBox(QGuiApplication::applicationDisplayName());
- mainLayout = new QVBoxLayout(groupBox);
- outerHorizontalLayout->addWidget(groupBox);
- outerHorizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
- outerVerticalLayout->addLayout(outerHorizontalLayout);
- outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
- } else {
- mainLayout = new QVBoxLayout(this);
- }
+ auto buttonLayout = new QHBoxLayout;
+ buttonLayout->addStretch(1);
+ buttonLayout->addWidget(quitButton);
+ buttonLayout->addStretch(1);
+
+ QVBoxLayout *mainLayout = nullptr;
+ if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
+ auto outerVerticalLayout = new QVBoxLayout(this);
+ outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
+ auto outerHorizontalLayout = new QHBoxLayout;
+ outerHorizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
+ auto groupBox = new QGroupBox(QGuiApplication::applicationDisplayName());
+ mainLayout = new QVBoxLayout(groupBox);
+ outerHorizontalLayout->addWidget(groupBox);
+ outerHorizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
+ outerVerticalLayout->addLayout(outerHorizontalLayout);
+ outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
+ } else {
+ mainLayout = new QVBoxLayout(this);
+ }
- mainLayout->addWidget(statusLabel);
- mainLayout->addLayout(buttonLayout);
+ mainLayout->addWidget(statusLabel);
+ mainLayout->addLayout(buttonLayout);
- setWindowTitle(QGuiApplication::applicationDisplayName());
+ setWindowTitle(QGuiApplication::applicationDisplayName());
}
void Server::sessionOpened()
@@ -183,9 +180,9 @@ void Server::sendFortune()
//! [5]
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
- out.setVersion(QDataStream::Qt_4_0);
+ out.setVersion(QDataStream::Qt_5_10);
- out << fortunes.at(qrand() % fortunes.size());
+ out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())];
//! [4] //! [7]
QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
diff --git a/examples/network/fortuneserver/server.h b/examples/network/fortuneserver/server.h
index ea5ed78292..c5bfa7d928 100644
--- a/examples/network/fortuneserver/server.h
+++ b/examples/network/fortuneserver/server.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -52,10 +52,11 @@
#define SERVER_H
#include <QDialog>
+#include <QString>
+#include <QVector>
QT_BEGIN_NAMESPACE
class QLabel;
-class QPushButton;
class QTcpServer;
class QNetworkSession;
QT_END_NAMESPACE
@@ -66,17 +67,17 @@ class Server : public QDialog
Q_OBJECT
public:
- explicit Server(QWidget *parent = Q_NULLPTR);
+ explicit Server(QWidget *parent = nullptr);
private slots:
void sessionOpened();
void sendFortune();
private:
- QLabel *statusLabel;
- QTcpServer *tcpServer;
- QStringList fortunes;
- QNetworkSession *networkSession;
+ QLabel *statusLabel = nullptr;
+ QTcpServer *tcpServer = nullptr;
+ QVector<QString> fortunes;
+ QNetworkSession *networkSession = nullptr;
};
//! [0]
diff --git a/examples/network/googlesuggest/googlesuggest.cpp b/examples/network/googlesuggest/googlesuggest.cpp
index 9fdfd8faa6..24fdde0a5c 100644
--- a/examples/network/googlesuggest/googlesuggest.cpp
+++ b/examples/network/googlesuggest/googlesuggest.cpp
@@ -51,7 +51,7 @@
//! [1]
#include "googlesuggest.h"
-#define GSUGGEST_URL "http://google.com/complete/search?output=toolbar&q=%1"
+const QString gsuggestUrl(QStringLiteral("http://google.com/complete/search?output=toolbar&q=%1"));
//! [1]
//! [2]
@@ -77,11 +77,10 @@ GSuggestCompletion::GSuggestCompletion(QLineEdit *parent): QObject(parent), edit
connect(popup, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
SLOT(doneCompletion()));
- timer = new QTimer(this);
- timer->setSingleShot(true);
- timer->setInterval(500);
- connect(timer, SIGNAL(timeout()), SLOT(autoSuggest()));
- connect(editor, SIGNAL(textEdited(QString)), timer, SLOT(start()));
+ timer.setSingleShot(true);
+ timer.setInterval(500);
+ connect(&timer, SIGNAL(timeout()), SLOT(autoSuggest()));
+ connect(editor, SIGNAL(textEdited(QString)), &timer, SLOT(start()));
connect(&networkManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(handleNetworkData(QNetworkReply*)));
@@ -109,7 +108,6 @@ bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev)
}
if (ev->type() == QEvent::KeyPress) {
-
bool consumed = false;
int key = static_cast<QKeyEvent*>(ev)->key();
switch (key) {
@@ -148,9 +146,8 @@ bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev)
//! [4]
//! [5]
-void GSuggestCompletion::showCompletion(const QStringList &choices)
+void GSuggestCompletion::showCompletion(const QVector<QString> &choices)
{
-
if (choices.isEmpty())
return;
@@ -159,12 +156,13 @@ void GSuggestCompletion::showCompletion(const QStringList &choices)
popup->setUpdatesEnabled(false);
popup->clear();
- for (int i = 0; i < choices.count(); ++i) {
- QTreeWidgetItem * item;
- item = new QTreeWidgetItem(popup);
- item->setText(0, choices[i]);
+
+ for (const auto &choice : choices) {
+ auto item = new QTreeWidgetItem(popup);
+ item->setText(0, choice);
item->setTextColor(0, color);
}
+
popup->setCurrentItem(popup->topLevelItem(0));
popup->resizeColumnToContents(0);
popup->setUpdatesEnabled(true);
@@ -178,7 +176,7 @@ void GSuggestCompletion::showCompletion(const QStringList &choices)
//! [6]
void GSuggestCompletion::doneCompletion()
{
- timer->stop();
+ timer.stop();
popup->hide();
editor->setFocus();
QTreeWidgetItem *item = popup->currentItem();
@@ -193,15 +191,15 @@ void GSuggestCompletion::doneCompletion()
void GSuggestCompletion::autoSuggest()
{
QString str = editor->text();
- QString url = QString(GSUGGEST_URL).arg(str);
- networkManager.get(QNetworkRequest(QString(url)));
+ QString url = gsuggestUrl.arg(str);
+ networkManager.get(QNetworkRequest(url));
}
//! [7]
//! [8]
void GSuggestCompletion::preventSuggest()
{
- timer->stop();
+ timer.stop();
}
//! [8]
@@ -209,8 +207,8 @@ void GSuggestCompletion::preventSuggest()
void GSuggestCompletion::handleNetworkData(QNetworkReply *networkReply)
{
QUrl url = networkReply->url();
- if (!networkReply->error()) {
- QStringList choices;
+ if (networkReply->error() == QNetworkReply::NoError) {
+ QVector<QString> choices;
QByteArray response(networkReply->readAll());
QXmlStreamReader xml(response);
diff --git a/examples/network/googlesuggest/googlesuggest.h b/examples/network/googlesuggest/googlesuggest.h
index 1d42f31571..a0b0ac069c 100644
--- a/examples/network/googlesuggest/googlesuggest.h
+++ b/examples/network/googlesuggest/googlesuggest.h
@@ -53,14 +53,7 @@
#include <QtWidgets>
#include <QtNetwork>
-#include <QObject>
-
-QT_BEGIN_NAMESPACE
-class QLineEdit;
-class QNetworkReply;
-class QTimer;
-class QTreeWidget;
-QT_END_NAMESPACE
+#include <QtCore>
//! [1]
class GSuggestCompletion : public QObject
@@ -68,10 +61,10 @@ class GSuggestCompletion : public QObject
Q_OBJECT
public:
- GSuggestCompletion(QLineEdit *parent = 0);
+ explicit GSuggestCompletion(QLineEdit *parent = nullptr);
~GSuggestCompletion();
bool eventFilter(QObject *obj, QEvent *ev) override;
- void showCompletion(const QStringList &choices);
+ void showCompletion(const QVector<QString> &choices);
public slots:
@@ -81,9 +74,9 @@ public slots:
void handleNetworkData(QNetworkReply *networkReply);
private:
- QLineEdit *editor;
- QTreeWidget *popup;
- QTimer *timer;
+ QLineEdit *editor = nullptr;
+ QTreeWidget *popup = nullptr;
+ QTimer timer;
QNetworkAccessManager networkManager;
};
//! [1]
diff --git a/examples/network/googlesuggest/googlesuggest.pro b/examples/network/googlesuggest/googlesuggest.pro
index 84db77e30b..6e73906303 100644
--- a/examples/network/googlesuggest/googlesuggest.pro
+++ b/examples/network/googlesuggest/googlesuggest.pro
@@ -1,4 +1,5 @@
QT += network widgets
+requires(qtConfig(itemviews))
SOURCES = main.cpp searchbox.cpp googlesuggest.cpp
HEADERS = searchbox.h googlesuggest.h
diff --git a/examples/network/googlesuggest/main.cpp b/examples/network/googlesuggest/main.cpp
index 9de966d7a5..ab819c5502 100644
--- a/examples/network/googlesuggest/main.cpp
+++ b/examples/network/googlesuggest/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -55,7 +55,7 @@
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
- SearchBox *searchEdit = new SearchBox;
- searchEdit->show();
+ SearchBox searchEdit;
+ searchEdit.show();
return app.exec();
}
diff --git a/examples/network/googlesuggest/searchbox.cpp b/examples/network/googlesuggest/searchbox.cpp
index e0754a7de2..d0bdb70daa 100644
--- a/examples/network/googlesuggest/searchbox.cpp
+++ b/examples/network/googlesuggest/searchbox.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -54,7 +54,7 @@
#include "searchbox.h"
#include "googlesuggest.h"
-#define GSEARCH_URL "http://www.google.com/search?q=%1"
+const QString gsearchUrl = QStringLiteral("http://www.google.com/search?q=%1");
//! [1]
SearchBox::SearchBox(QWidget *parent): QLineEdit(parent)
@@ -75,8 +75,8 @@ SearchBox::SearchBox(QWidget *parent): QLineEdit(parent)
void SearchBox::doSearch()
{
completer->preventSuggest();
- QString url = QString(GSEARCH_URL).arg(text());
- QDesktopServices::openUrl(QUrl(url));
+ QString url = gsearchUrl.arg(text());
+ QDesktopServices::openUrl(url);
}
//! [2]
diff --git a/examples/network/googlesuggest/searchbox.h b/examples/network/googlesuggest/searchbox.h
index eea5854de8..fbd33011b7 100644
--- a/examples/network/googlesuggest/searchbox.h
+++ b/examples/network/googlesuggest/searchbox.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -61,13 +61,13 @@ class SearchBox: public QLineEdit
Q_OBJECT
public:
- SearchBox(QWidget *parent = 0);
+ explicit SearchBox(QWidget *parent = nullptr);
protected slots:
void doSearch();
private:
- GSuggestCompletion *completer;
+ GSuggestCompletion *completer = nullptr;
//! [1]
};
diff --git a/examples/network/http/httpwindow.cpp b/examples/network/http/httpwindow.cpp
index fddd2c809a..ec90b8f7fe 100644
--- a/examples/network/http/httpwindow.cpp
+++ b/examples/network/http/httpwindow.cpp
@@ -55,12 +55,12 @@
#include "httpwindow.h"
#include "ui_authenticationdialog.h"
-#ifndef QT_NO_SSL
-static const char defaultUrl[] = "https://www.qt.io/";
+#if QT_CONFIG(ssl)
+const char defaultUrl[] = "https://www.qt.io/";
#else
-static const char defaultUrl[] = "http://www.qt.io/";
+const char defaultUrl[] = "http://www.qt.io/";
#endif
-static const char defaultFileName[] = "index.html";
+const char defaultFileName[] = "index.html";
ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
: QProgressDialog(parent)
@@ -71,6 +71,7 @@ ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
setMinimum(0);
setValue(0);
setMinimumDuration(0);
+ setMinimumSize(QSize(400, 75));
}
void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes)
@@ -87,8 +88,8 @@ HttpWindow::HttpWindow(QWidget *parent)
, launchCheckBox(new QCheckBox("Launch file"))
, defaultFileLineEdit(new QLineEdit(defaultFileName))
, downloadDirectoryLineEdit(new QLineEdit)
- , reply(Q_NULLPTR)
- , file(Q_NULLPTR)
+ , reply(nullptr)
+ , file(nullptr)
, httpRequestAborted(false)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
@@ -174,15 +175,22 @@ void HttpWindow::downloadFile()
if (fileName.isEmpty())
fileName = defaultFileName;
QString downloadDirectory = QDir::cleanPath(downloadDirectoryLineEdit->text().trimmed());
- if (!downloadDirectory.isEmpty() && QFileInfo(downloadDirectory).isDir())
+ bool useDirectory = !downloadDirectory.isEmpty() && QFileInfo(downloadDirectory).isDir();
+ if (useDirectory)
fileName.prepend(downloadDirectory + '/');
if (QFile::exists(fileName)) {
if (QMessageBox::question(this, tr("Overwrite Existing File"),
- tr("There already exists a file called %1 in "
- "the current directory. Overwrite?").arg(fileName),
- QMessageBox::Yes|QMessageBox::No, QMessageBox::No)
- == QMessageBox::No)
+ tr("There already exists a file called %1%2."
+ " Overwrite?")
+ .arg(fileName,
+ useDirectory
+ ? QString()
+ : QStringLiteral(" in the current directory")),
+ QMessageBox::Yes | QMessageBox::No,
+ QMessageBox::No)
+ == QMessageBox::No) {
return;
+ }
QFile::remove(fileName);
}
@@ -204,7 +212,7 @@ QFile *HttpWindow::openFileForWrite(const QString &fileName)
tr("Unable to save the file %1: %2.")
.arg(QDir::toNativeSeparators(fileName),
file->errorString()));
- return Q_NULLPTR;
+ return nullptr;
}
return file.take();
}
@@ -224,12 +232,12 @@ void HttpWindow::httpFinished()
fi.setFile(file->fileName());
file->close();
delete file;
- file = Q_NULLPTR;
+ file = nullptr;
}
if (httpRequestAborted) {
reply->deleteLater();
- reply = Q_NULLPTR;
+ reply = nullptr;
return;
}
@@ -238,21 +246,23 @@ void HttpWindow::httpFinished()
statusLabel->setText(tr("Download failed:\n%1.").arg(reply->errorString()));
downloadButton->setEnabled(true);
reply->deleteLater();
- reply = Q_NULLPTR;
+ reply = nullptr;
return;
}
const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
reply->deleteLater();
- reply = Q_NULLPTR;
+ reply = nullptr;
if (!redirectionTarget.isNull()) {
const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl());
if (QMessageBox::question(this, tr("Redirect"),
tr("Redirect to %1 ?").arg(redirectedUrl.toString()),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
+ QFile::remove(fi.absoluteFilePath());
downloadButton->setEnabled(true);
+ statusLabel->setText(tr("Download failed:\nRedirect rejected."));
return;
}
file = openFileForWrite(fi.absoluteFilePath());
@@ -286,7 +296,7 @@ void HttpWindow::enableDownloadButton()
downloadButton->setEnabled(!urlLineEdit->text().isEmpty());
}
-void HttpWindow::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authenticator)
+void HttpWindow::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator)
{
QDialog authenticationDialog;
Ui::Dialog ui;
@@ -306,7 +316,7 @@ void HttpWindow::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authe
}
#ifndef QT_NO_SSL
-void HttpWindow::sslErrors(QNetworkReply*,const QList<QSslError> &errors)
+void HttpWindow::sslErrors(QNetworkReply *, const QList<QSslError> &errors)
{
QString errorString;
foreach (const QSslError &error, errors) {
diff --git a/examples/network/http/httpwindow.h b/examples/network/http/httpwindow.h
index 3bb43dbf89..20ad2bb4da 100644
--- a/examples/network/http/httpwindow.h
+++ b/examples/network/http/httpwindow.h
@@ -71,7 +71,7 @@ class ProgressDialog : public QProgressDialog {
Q_OBJECT
public:
- explicit ProgressDialog(const QUrl &url, QWidget *parent = Q_NULLPTR);
+ explicit ProgressDialog(const QUrl &url, QWidget *parent = nullptr);
public slots:
void networkReplyProgress(qint64 bytesRead, qint64 totalBytes);
@@ -82,7 +82,7 @@ class HttpWindow : public QDialog
Q_OBJECT
public:
- explicit HttpWindow(QWidget *parent = Q_NULLPTR);
+ explicit HttpWindow(QWidget *parent = nullptr);
void startRequest(const QUrl &requestedUrl);
@@ -92,9 +92,9 @@ private slots:
void httpFinished();
void httpReadyRead();
void enableDownloadButton();
- void slotAuthenticationRequired(QNetworkReply*,QAuthenticator *);
+ void slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator);
#ifndef QT_NO_SSL
- void sslErrors(QNetworkReply*,const QList<QSslError> &errors);
+ void sslErrors(QNetworkReply *, const QList<QSslError> &errors);
#endif
private:
diff --git a/examples/network/multicastreceiver/multicastreceiver.pro b/examples/network/multicastreceiver/multicastreceiver.pro
index 6906fc6cb5..e9bcb45a8d 100644
--- a/examples/network/multicastreceiver/multicastreceiver.pro
+++ b/examples/network/multicastreceiver/multicastreceiver.pro
@@ -1,4 +1,5 @@
QT += network widgets
+requires(qtConfig(udpsocket))
HEADERS = receiver.h
SOURCES = receiver.cpp \
diff --git a/examples/network/multicastreceiver/receiver.cpp b/examples/network/multicastreceiver/receiver.cpp
index 10154c60cc..d793242ad0 100644
--- a/examples/network/multicastreceiver/receiver.cpp
+++ b/examples/network/multicastreceiver/receiver.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -54,41 +54,56 @@
#include "receiver.h"
Receiver::Receiver(QWidget *parent)
- : QDialog(parent)
+ : QDialog(parent),
+ groupAddress4(QStringLiteral("239.255.43.21")),
+ groupAddress6(QStringLiteral("ff12::2115"))
{
- groupAddress = QHostAddress("239.255.43.21");
+ statusLabel = new QLabel(tr("Listening for multicast messages on both IPv4 and IPv6"));
+ auto quitButton = new QPushButton(tr("&Quit"));
- statusLabel = new QLabel(tr("Listening for multicasted messages"));
- quitButton = new QPushButton(tr("&Quit"));
-
- udpSocket = new QUdpSocket(this);
- udpSocket->bind(QHostAddress::AnyIPv4, 45454, QUdpSocket::ShareAddress);
- udpSocket->joinMulticastGroup(groupAddress);
-
- connect(udpSocket, SIGNAL(readyRead()),
- this, SLOT(processPendingDatagrams()));
- connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
-
- QHBoxLayout *buttonLayout = new QHBoxLayout;
+ auto buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
- QVBoxLayout *mainLayout = new QVBoxLayout;
+ auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle(tr("Multicast Receiver"));
+
+ udpSocket4.bind(QHostAddress::AnyIPv4, 45454, QUdpSocket::ShareAddress);
+ udpSocket4.joinMulticastGroup(groupAddress4);
+
+ if (!udpSocket6.bind(QHostAddress::AnyIPv6, 45454, QUdpSocket::ShareAddress) ||
+ !udpSocket6.joinMulticastGroup(groupAddress6))
+ statusLabel->setText(tr("Listening for multicast messages on IPv4 only"));
+
+ connect(&udpSocket4, SIGNAL(readyRead()),
+ this, SLOT(processPendingDatagrams()));
+ connect(&udpSocket6, &QUdpSocket::readyRead, this, &Receiver::processPendingDatagrams);
+ connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
}
void Receiver::processPendingDatagrams()
{
- while (udpSocket->hasPendingDatagrams()) {
- QByteArray datagram;
- datagram.resize(udpSocket->pendingDatagramSize());
- udpSocket->readDatagram(datagram.data(), datagram.size());
- statusLabel->setText(tr("Received datagram: \"%1\"")
- .arg(datagram.data()));
+ QByteArray datagram;
+
+ // using QUdpSocket::readDatagram (API since Qt 4)
+ while (udpSocket4.hasPendingDatagrams()) {
+ datagram.resize(int(udpSocket4.pendingDatagramSize()));
+ udpSocket4.readDatagram(datagram.data(), datagram.size());
+ statusLabel->setText(tr("Received IPv4 datagram: \"%1\"")
+ .arg(datagram.constData()));
+ }
+
+ // using QUdpSocket::receiveDatagram (API since Qt 5.8)
+ while (udpSocket6.hasPendingDatagrams()) {
+ QNetworkDatagram dgram = udpSocket6.receiveDatagram();
+ statusLabel->setText(statusLabel->text() +
+ tr("\nReceived IPv6 datagram from [%2]:%3: \"%1\"")
+ .arg(dgram.data().constData(), dgram.senderAddress().toString())
+ .arg(dgram.senderPort()));
}
}
diff --git a/examples/network/multicastreceiver/receiver.h b/examples/network/multicastreceiver/receiver.h
index efef1cdb30..0325d861df 100644
--- a/examples/network/multicastreceiver/receiver.h
+++ b/examples/network/multicastreceiver/receiver.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -53,11 +53,10 @@
#include <QDialog>
#include <QHostAddress>
+#include <QUdpSocket>
QT_BEGIN_NAMESPACE
class QLabel;
-class QPushButton;
-class QUdpSocket;
QT_END_NAMESPACE
class Receiver : public QDialog
@@ -65,16 +64,17 @@ class Receiver : public QDialog
Q_OBJECT
public:
- Receiver(QWidget *parent = 0);
+ explicit Receiver(QWidget *parent = nullptr);
private slots:
void processPendingDatagrams();
private:
- QLabel *statusLabel;
- QPushButton *quitButton;
- QUdpSocket *udpSocket;
- QHostAddress groupAddress;
+ QLabel *statusLabel = nullptr;
+ QUdpSocket udpSocket4;
+ QUdpSocket udpSocket6;
+ QHostAddress groupAddress4;
+ QHostAddress groupAddress6;
};
#endif
diff --git a/examples/network/multicastsender/multicastsender.pro b/examples/network/multicastsender/multicastsender.pro
index 4797b194a9..160f37be6d 100644
--- a/examples/network/multicastsender/multicastsender.pro
+++ b/examples/network/multicastsender/multicastsender.pro
@@ -2,6 +2,7 @@ HEADERS = sender.h
SOURCES = sender.cpp \
main.cpp
QT += network widgets
+requires(qtConfig(udpsocket))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/network/multicastsender
diff --git a/examples/network/multicastsender/sender.cpp b/examples/network/multicastsender/sender.cpp
index 4aa65fee27..a542a2528f 100644
--- a/examples/network/multicastsender/sender.cpp
+++ b/examples/network/multicastsender/sender.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,43 +48,45 @@
**
****************************************************************************/
-#include <QtWidgets>
-#include <QtNetwork>
-
#include "sender.h"
Sender::Sender(QWidget *parent)
- : QDialog(parent)
+ : QDialog(parent),
+ groupAddress4(QStringLiteral("239.255.43.21")),
+ groupAddress6(QStringLiteral("ff12::2115"))
{
- groupAddress = QHostAddress("239.255.43.21");
+ // force binding to their respective families
+ udpSocket4.bind(QHostAddress(QHostAddress::AnyIPv4), 0);
+ udpSocket6.bind(QHostAddress(QHostAddress::AnyIPv6), udpSocket4.localPort());
- statusLabel = new QLabel(tr("Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress.toString()));
+ QString msg = tr("Ready to multicast datagrams to groups %1 and [%2] on port 45454").arg(groupAddress4.toString());
+ if (udpSocket6.state() != QAbstractSocket::BoundState)
+ msg = tr("IPv6 failed. Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress4.toString());
+ else
+ msg = msg.arg(groupAddress6.toString());
+ statusLabel = new QLabel(msg);
- ttlLabel = new QLabel(tr("TTL for multicast datagrams:"));
- ttlSpinBox = new QSpinBox;
+ auto ttlLabel = new QLabel(tr("TTL for IPv4 multicast datagrams:"));
+ auto ttlSpinBox = new QSpinBox;
ttlSpinBox->setRange(0, 255);
- QHBoxLayout *ttlLayout = new QHBoxLayout;
+ auto ttlLayout = new QHBoxLayout;
ttlLayout->addWidget(ttlLabel);
ttlLayout->addWidget(ttlSpinBox);
startButton = new QPushButton(tr("&Start"));
- quitButton = new QPushButton(tr("&Quit"));
+ auto quitButton = new QPushButton(tr("&Quit"));
- buttonBox = new QDialogButtonBox;
+ auto buttonBox = new QDialogButtonBox;
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
- timer = new QTimer(this);
- udpSocket = new QUdpSocket(this);
- messageNo = 1;
-
- connect(ttlSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ttlChanged(int)));
- connect(startButton, SIGNAL(clicked()), this, SLOT(startSending()));
- connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
- connect(timer, SIGNAL(timeout()), this, SLOT(sendDatagram()));
+ connect(ttlSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &Sender::ttlChanged);
+ connect(startButton, &QPushButton::clicked, this, &Sender::startSending);
+ connect(quitButton, &QPushButton::clicked, this, &Sender::close);
+ connect(&timer, &QTimer::timeout, this, &Sender::sendDatagram);
- QVBoxLayout *mainLayout = new QVBoxLayout;
+ auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(ttlLayout);
mainLayout->addWidget(buttonBox);
@@ -96,20 +98,22 @@ Sender::Sender(QWidget *parent)
void Sender::ttlChanged(int newTtl)
{
- udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
+ // we only set the TTL on the IPv4 socket, as that changes the multicast scope
+ udpSocket4.setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
}
void Sender::startSending()
{
startButton->setEnabled(false);
- timer->start(1000);
+ timer.start(1000);
}
void Sender::sendDatagram()
{
statusLabel->setText(tr("Now sending datagram %1").arg(messageNo));
QByteArray datagram = "Multicast message " + QByteArray::number(messageNo);
- udpSocket->writeDatagram(datagram.data(), datagram.size(),
- groupAddress, 45454);
+ udpSocket4.writeDatagram(datagram, groupAddress4, 45454);
+ if (udpSocket6.state() == QAbstractSocket::BoundState)
+ udpSocket6.writeDatagram(datagram, groupAddress6, 45454);
++messageNo;
}
diff --git a/examples/network/multicastsender/sender.h b/examples/network/multicastsender/sender.h
index 8e10f88c0d..0af6f9aaec 100644
--- a/examples/network/multicastsender/sender.h
+++ b/examples/network/multicastsender/sender.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -51,24 +51,16 @@
#ifndef SENDER_H
#define SENDER_H
-#include <QDialog>
-#include <QHostAddress>
-
-QT_BEGIN_NAMESPACE
-class QDialogButtonBox;
-class QLabel;
-class QPushButton;
-class QTimer;
-class QUdpSocket;
-class QSpinBox;
-QT_END_NAMESPACE
+#include <QtWidgets>
+#include <QtNetwork>
+#include <QtCore>
class Sender : public QDialog
{
Q_OBJECT
public:
- Sender(QWidget *parent = 0);
+ explicit Sender(QWidget *parent = nullptr);
private slots:
void ttlChanged(int newTtl);
@@ -76,16 +68,14 @@ private slots:
void sendDatagram();
private:
- QLabel *statusLabel;
- QLabel *ttlLabel;
- QSpinBox *ttlSpinBox;
- QPushButton *startButton;
- QPushButton *quitButton;
- QDialogButtonBox *buttonBox;
- QUdpSocket *udpSocket;
- QTimer *timer;
- QHostAddress groupAddress;
- int messageNo;
+ QLabel *statusLabel = nullptr;
+ QPushButton *startButton = nullptr;
+ QUdpSocket udpSocket4;
+ QUdpSocket udpSocket6;
+ QTimer timer;
+ QHostAddress groupAddress4;
+ QHostAddress groupAddress6;
+ int messageNo = 1;
};
#endif
diff --git a/examples/network/network-chat/network-chat.pro b/examples/network/network-chat/network-chat.pro
index b20e8b2934..2e3cbbc489 100644
--- a/examples/network/network-chat/network-chat.pro
+++ b/examples/network/network-chat/network-chat.pro
@@ -11,6 +11,8 @@ SOURCES = chatdialog.cpp \
server.cpp
FORMS = chatdialog.ui
QT += network widgets
+requires(qtConfig(udpsocket))
+requires(qtConfig(listwidget))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/network/network-chat
diff --git a/examples/network/securesocketclient/certificateinfo.cpp b/examples/network/securesocketclient/certificateinfo.cpp
index c8cd86bc72..81429fc655 100644
--- a/examples/network/securesocketclient/certificateinfo.cpp
+++ b/examples/network/securesocketclient/certificateinfo.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -57,8 +57,8 @@ CertificateInfo::CertificateInfo(QWidget *parent)
form = new Ui_CertificateInfo;
form->setupUi(this);
- connect(form->certificationPathView, SIGNAL(currentIndexChanged(int)),
- this, SLOT(updateCertificateInfo(int)));
+ connect(form->certificationPathView, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &CertificateInfo::updateCertificateInfo);
}
CertificateInfo::~CertificateInfo()
@@ -68,25 +68,23 @@ CertificateInfo::~CertificateInfo()
void CertificateInfo::setCertificateChain(const QList<QSslCertificate> &chain)
{
- this->chain = chain;
+ certificateChain = chain;
form->certificationPathView->clear();
-
- for (int i = 0; i < chain.size(); ++i) {
- const QSslCertificate &cert = chain.at(i);
+ for (int i = 0; i < certificateChain.size(); ++i) {
+ const QSslCertificate &cert = certificateChain.at(i);
form->certificationPathView->addItem(tr("%1%2 (%3)").arg(!i ? QString() : tr("Issued by: "))
.arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
.arg(cert.subjectInfo(QSslCertificate::CommonName).join(QLatin1Char(' '))));
}
-
form->certificationPathView->setCurrentIndex(0);
}
void CertificateInfo::updateCertificateInfo(int index)
{
form->certificateInfoView->clear();
- if (index >= 0 && index < chain.size()) {
- const QSslCertificate &cert = chain.at(index);
+ if (index >= 0 && index < certificateChain.size()) {
+ const QSslCertificate &cert = certificateChain.at(index);
QStringList lines;
lines << tr("Organization: %1").arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
<< tr("Subunit: %1").arg(cert.subjectInfo(QSslCertificate::OrganizationalUnitName).join(QLatin1Char(' ')))
@@ -101,9 +99,7 @@ void CertificateInfo::updateCertificateInfo(int index)
<< tr("Issuer Locality: %1").arg(cert.issuerInfo(QSslCertificate::LocalityName).join(QLatin1Char(' ')))
<< tr("Issuer State/Province: %1").arg(cert.issuerInfo(QSslCertificate::StateOrProvinceName).join(QLatin1Char(' ')))
<< tr("Issuer Common Name: %1").arg(cert.issuerInfo(QSslCertificate::CommonName).join(QLatin1Char(' ')));
- foreach (QString line, lines)
+ for (const auto &line : lines)
form->certificateInfoView->addItem(line);
- } else {
- form->certificateInfoView->clear();
}
}
diff --git a/examples/network/securesocketclient/certificateinfo.h b/examples/network/securesocketclient/certificateinfo.h
index abc56dfbcd..9e079c5603 100644
--- a/examples/network/securesocketclient/certificateinfo.h
+++ b/examples/network/securesocketclient/certificateinfo.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -51,8 +51,9 @@
#ifndef CERTIFICATEINFO_H
#define CERTIFICATEINFO_H
-#include <QtWidgets/QDialog>
-#include <QtNetwork/QSslCertificate>
+#include <QDialog>
+#include <QList>
+#include <QSslCertificate>
QT_BEGIN_NAMESPACE
class Ui_CertificateInfo;
@@ -62,7 +63,7 @@ class CertificateInfo : public QDialog
{
Q_OBJECT
public:
- CertificateInfo(QWidget *parent = 0);
+ explicit CertificateInfo(QWidget *parent = nullptr);
~CertificateInfo();
void setCertificateChain(const QList<QSslCertificate> &chain);
@@ -71,8 +72,8 @@ private slots:
void updateCertificateInfo(int index);
private:
- Ui_CertificateInfo *form;
- QList<QSslCertificate> chain;
+ Ui_CertificateInfo *form = nullptr;
+ QList<QSslCertificate> certificateChain;
};
#endif
diff --git a/examples/network/securesocketclient/certificateinfo.ui b/examples/network/securesocketclient/certificateinfo.ui
index c5238eb3e1..3bea255e9e 100644
--- a/examples/network/securesocketclient/certificateinfo.ui
+++ b/examples/network/securesocketclient/certificateinfo.ui
@@ -42,7 +42,7 @@
<widget class="QListWidget" name="certificateInfoView">
<property name="font">
<font>
- <pointsize>8</pointsize>
+ <pointsize>10</pointsize>
</font>
</property>
<property name="wordWrap">
diff --git a/examples/network/securesocketclient/main.cpp b/examples/network/securesocketclient/main.cpp
index e6dc60736f..e9c413577f 100644
--- a/examples/network/securesocketclient/main.cpp
+++ b/examples/network/securesocketclient/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -50,6 +50,9 @@
#include <QApplication>
#include <QMessageBox>
+#include <QtNetwork>
+
+QT_REQUIRE_CONFIG(ssl);
#include "sslclient.h"
@@ -61,7 +64,7 @@ int main(int argc, char **argv)
if (!QSslSocket::supportsSsl()) {
QMessageBox::information(0, "Secure Socket Client",
- "This system does not support OpenSSL.");
+ "This system does not support SSL/TLS.");
return -1;
}
diff --git a/examples/network/securesocketclient/securesocketclient.pro b/examples/network/securesocketclient/securesocketclient.pro
index f13ed57247..fb81ef6ed2 100644
--- a/examples/network/securesocketclient/securesocketclient.pro
+++ b/examples/network/securesocketclient/securesocketclient.pro
@@ -1,3 +1,5 @@
+requires(qtHaveModule(network))
+
HEADERS += certificateinfo.h \
sslclient.h
SOURCES += certificateinfo.cpp \
@@ -8,6 +10,8 @@ FORMS += certificateinfo.ui \
sslclient.ui \
sslerrors.ui
QT += network widgets
+requires(qtConfig(listwidget))
+requires(qtConfig(combobox))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/network/securesocketclient
diff --git a/examples/network/securesocketclient/sslclient.cpp b/examples/network/securesocketclient/sslclient.cpp
index 46d1919fd0..afeec033ff 100644
--- a/examples/network/securesocketclient/sslclient.cpp
+++ b/examples/network/securesocketclient/sslclient.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -50,29 +50,17 @@
#include "certificateinfo.h"
#include "sslclient.h"
+
#include "ui_sslclient.h"
#include "ui_sslerrors.h"
-#include <QtWidgets/QScrollBar>
-#include <QtWidgets/QStyle>
-#include <QtWidgets/QToolButton>
-#include <QtWidgets/QMessageBox>
-#include <QtNetwork/QSslCipher>
+#include <QtCore>
SslClient::SslClient(QWidget *parent)
- : QWidget(parent), socket(0), padLock(0), executingDialog(false)
+ : QWidget(parent)
{
- form = new Ui_Form;
- form->setupUi(this);
- form->hostNameEdit->setSelection(0, form->hostNameEdit->text().size());
- form->sessionOutput->setHtml(tr("&lt;not connected&gt;"));
-
- connect(form->hostNameEdit, SIGNAL(textChanged(QString)),
- this, SLOT(updateEnabledState()));
- connect(form->connectButton, SIGNAL(clicked()),
- this, SLOT(secureConnect()));
- connect(form->sendButton, SIGNAL(clicked()),
- this, SLOT(sendData()));
+ setupUi();
+ setupSecureSocket();
}
SslClient::~SslClient()
@@ -82,17 +70,15 @@ SslClient::~SslClient()
void SslClient::updateEnabledState()
{
- bool unconnected = !socket || socket->state() == QAbstractSocket::UnconnectedState;
-
+ const bool unconnected = socket->state() == QAbstractSocket::UnconnectedState;
form->hostNameEdit->setReadOnly(!unconnected);
form->hostNameEdit->setFocusPolicy(unconnected ? Qt::StrongFocus : Qt::NoFocus);
-
form->hostNameLabel->setEnabled(unconnected);
form->portBox->setEnabled(unconnected);
form->portLabel->setEnabled(unconnected);
form->connectButton->setEnabled(unconnected && !form->hostNameEdit->text().isEmpty());
- bool connected = socket && socket->state() == QAbstractSocket::ConnectedState;
+ const bool connected = socket->state() == QAbstractSocket::ConnectedState;
form->sessionOutput->setEnabled(connected);
form->sessionInput->setEnabled(connected);
form->sessionInputLabel->setEnabled(connected);
@@ -101,20 +87,6 @@ void SslClient::updateEnabledState()
void SslClient::secureConnect()
{
- if (!socket) {
- socket = new QSslSocket(this);
- connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
- this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
- connect(socket, SIGNAL(encrypted()),
- this, SLOT(socketEncrypted()));
- connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
- this, SLOT(socketError(QAbstractSocket::SocketError)));
- connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
- this, SLOT(sslErrors(QList<QSslError>)));
- connect(socket, SIGNAL(readyRead()),
- this, SLOT(socketReadyRead()));
- }
-
socket->connectToHostEncrypted(form->hostNameEdit->text(), form->portBox->value());
updateEnabledState();
}
@@ -125,20 +97,18 @@ void SslClient::socketStateChanged(QAbstractSocket::SocketState state)
return;
updateEnabledState();
+
if (state == QAbstractSocket::UnconnectedState) {
+ form->sessionInput->clear();
form->hostNameEdit->setPalette(QPalette());
form->hostNameEdit->setFocus();
form->cipherLabel->setText(tr("<none>"));
- if (padLock)
- padLock->hide();
+ padLock->hide();
}
}
void SslClient::socketEncrypted()
{
- if (!socket)
- return; // might have disconnected already
-
form->sessionOutput->clear();
form->sessionInput->setFocus();
@@ -146,36 +116,12 @@ void SslClient::socketEncrypted()
palette.setColor(QPalette::Base, QColor(255, 255, 192));
form->hostNameEdit->setPalette(palette);
- QSslCipher ciph = socket->sessionCipher();
- QString cipher = QString("%1, %2 (%3/%4)").arg(ciph.authenticationMethod())
- .arg(ciph.name()).arg(ciph.usedBits()).arg(ciph.supportedBits());;
- form->cipherLabel->setText(cipher);
-
- if (!padLock) {
- padLock = new QToolButton;
- padLock->setIcon(QIcon(":/encrypted.png"));
-#ifndef QT_NO_CURSOR
- padLock->setCursor(Qt::ArrowCursor);
-#endif
- padLock->setToolTip(tr("Display encryption details."));
-
- int extent = form->hostNameEdit->height() - 2;
- padLock->resize(extent, extent);
- padLock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
-
- QHBoxLayout *layout = new QHBoxLayout(form->hostNameEdit);
- layout->setMargin(form->hostNameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
- layout->setSpacing(0);
- layout->addStretch();
- layout->addWidget(padLock);
-
- form->hostNameEdit->setLayout(layout);
-
- connect(padLock, SIGNAL(clicked()),
- this, SLOT(displayCertificateInfo()));
- } else {
- padLock->show();
- }
+ const QSslCipher cipher = socket->sessionCipher();
+ const QString cipherInfo = QString("%1, %2 (%3/%4)").arg(cipher.authenticationMethod())
+ .arg(cipher.name()).arg(cipher.usedBits())
+ .arg(cipher.supportedBits());;
+ form->cipherLabel->setText(cipherInfo);
+ padLock->show();
}
void SslClient::socketReadyRead()
@@ -185,7 +131,7 @@ void SslClient::socketReadyRead()
void SslClient::sendData()
{
- QString input = form->sessionInput->text();
+ const QString input = form->sessionInput->text();
appendString(input + '\n');
socket->write(input.toUtf8() + "\r\n");
form->sessionInput->clear();
@@ -193,7 +139,12 @@ void SslClient::sendData()
void SslClient::socketError(QAbstractSocket::SocketError)
{
+ if (handlingSocketError)
+ return;
+
+ handlingSocketError = true;
QMessageBox::critical(this, tr("Connection error"), socket->errorString());
+ handlingSocketError = false;
}
void SslClient::sslErrors(const QList<QSslError> &errors)
@@ -201,10 +152,10 @@ void SslClient::sslErrors(const QList<QSslError> &errors)
QDialog errorDialog(this);
Ui_SslErrors ui;
ui.setupUi(&errorDialog);
- connect(ui.certificateChainButton, SIGNAL(clicked()),
- this, SLOT(displayCertificateInfo()));
+ connect(ui.certificateChainButton, &QPushButton::clicked,
+ this, &SslClient::displayCertificateInfo);
- foreach (const QSslError &error, errors)
+ for (const auto &error : errors)
ui.sslErrorList->addItem(error.errorString());
executingDialog = true;
@@ -219,10 +170,69 @@ void SslClient::sslErrors(const QList<QSslError> &errors)
void SslClient::displayCertificateInfo()
{
- CertificateInfo *info = new CertificateInfo(this);
- info->setCertificateChain(socket->peerCertificateChain());
- info->exec();
- info->deleteLater();
+ CertificateInfo info;
+ info.setCertificateChain(socket->peerCertificateChain());
+ info.exec();
+}
+
+void SslClient::setupUi()
+{
+ if (form)
+ return;
+
+ form = new Ui_Form;
+ form->setupUi(this);
+ form->hostNameEdit->setSelection(0, form->hostNameEdit->text().size());
+ form->sessionOutput->setHtml(tr("&lt;not connected&gt;"));
+
+ connect(form->hostNameEdit, SIGNAL(textChanged(QString)),
+ this, SLOT(updateEnabledState()));
+ connect(form->connectButton, SIGNAL(clicked()),
+ this, SLOT(secureConnect()));
+ connect(form->sendButton, SIGNAL(clicked()),
+ this, SLOT(sendData()));
+
+ padLock = new QToolButton;
+ padLock->setIcon(QIcon(":/encrypted.png"));
+ connect(padLock, SIGNAL(clicked()), this, SLOT(displayCertificateInfo()));
+
+#if QT_CONFIG(cursor)
+ padLock->setCursor(Qt::ArrowCursor);
+#endif
+ padLock->setToolTip(tr("Display encryption details."));
+
+ const int extent = form->hostNameEdit->height() - 2;
+ padLock->resize(extent, extent);
+ padLock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
+
+ QHBoxLayout *layout = new QHBoxLayout(form->hostNameEdit);
+ layout->setMargin(form->hostNameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
+ layout->setSpacing(0);
+ layout->addStretch();
+ layout->addWidget(padLock);
+
+ form->hostNameEdit->setLayout(layout);
+ padLock->hide();
+}
+
+void SslClient::setupSecureSocket()
+{
+ if (socket)
+ return;
+
+ socket = new QSslSocket(this);
+
+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
+ this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
+ connect(socket, SIGNAL(encrypted()),
+ this, SLOT(socketEncrypted()));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(socketError(QAbstractSocket::SocketError)));
+ connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SLOT(sslErrors(QList<QSslError>)));
+ connect(socket, SIGNAL(readyRead()),
+ this, SLOT(socketReadyRead()));
+
}
void SslClient::appendString(const QString &line)
diff --git a/examples/network/securesocketclient/sslclient.h b/examples/network/securesocketclient/sslclient.h
index d3baefbc56..63fdbef77d 100644
--- a/examples/network/securesocketclient/sslclient.h
+++ b/examples/network/securesocketclient/sslclient.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -51,13 +51,13 @@
#ifndef SSLCLIENT_H
#define SSLCLIENT_H
-#include <QtWidgets/QWidget>
-#include <QtNetwork/QAbstractSocket>
-#include <QtNetwork/QSslSocket>
+#include <QtNetwork>
+
+QT_REQUIRE_CONFIG(ssl);
+
+#include <QtWidgets>
QT_BEGIN_NAMESPACE
-class QSslSocket;
-class QToolButton;
class Ui_Form;
QT_END_NAMESPACE
@@ -65,7 +65,7 @@ class SslClient : public QWidget
{
Q_OBJECT
public:
- SslClient(QWidget *parent = 0);
+ explicit SslClient(QWidget *parent = nullptr);
~SslClient();
private slots:
@@ -80,12 +80,15 @@ private slots:
void displayCertificateInfo();
private:
+ void setupUi();
+ void setupSecureSocket();
void appendString(const QString &line);
- QSslSocket *socket;
- QToolButton *padLock;
- Ui_Form *form;
- bool executingDialog;
+ QSslSocket *socket = nullptr;
+ QToolButton *padLock = nullptr;
+ Ui_Form *form = nullptr;
+ bool handlingSocketError = false;
+ bool executingDialog = false;
};
#endif
diff --git a/examples/network/securesocketclient/sslclient.ui b/examples/network/securesocketclient/sslclient.ui
index 19bae83a09..7821b04e76 100644
--- a/examples/network/securesocketclient/sslclient.ui
+++ b/examples/network/securesocketclient/sslclient.ui
@@ -10,6 +10,12 @@
<height>320</height>
</rect>
</property>
+ <property name="minimumSize">
+ <size>
+ <width>343</width>
+ <height>320</height>
+ </size>
+ </property>
<property name="windowTitle">
<string>Secure Socket Client</string>
</property>
@@ -114,8 +120,8 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'.SF NS Text'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
diff --git a/examples/network/threadedfortuneserver/fortuneserver.cpp b/examples/network/threadedfortuneserver/fortuneserver.cpp
index 01b77e2aba..791ffc71f4 100644
--- a/examples/network/threadedfortuneserver/fortuneserver.cpp
+++ b/examples/network/threadedfortuneserver/fortuneserver.cpp
@@ -51,6 +51,8 @@
#include "fortuneserver.h"
#include "fortunethread.h"
+#include <QRandomGenerator>
+
#include <stdlib.h>
//! [0]
@@ -70,7 +72,7 @@ FortuneServer::FortuneServer(QObject *parent)
//! [1]
void FortuneServer::incomingConnection(qintptr socketDescriptor)
{
- QString fortune = fortunes.at(qrand() % fortunes.size());
+ QString fortune = fortunes.at(QRandomGenerator::global()->bounded(fortunes.size()));
FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
diff --git a/examples/network/threadedfortuneserver/main.cpp b/examples/network/threadedfortuneserver/main.cpp
index 3a54585fbc..fdacb28945 100644
--- a/examples/network/threadedfortuneserver/main.cpp
+++ b/examples/network/threadedfortuneserver/main.cpp
@@ -60,6 +60,5 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
Dialog dialog;
dialog.show();
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
return app.exec();
}
diff --git a/examples/network/torrent/main.cpp b/examples/network/torrent/main.cpp
index de7516ed3f..6430d2e5f3 100644
--- a/examples/network/torrent/main.cpp
+++ b/examples/network/torrent/main.cpp
@@ -55,7 +55,6 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
Q_INIT_RESOURCE(icons);
diff --git a/examples/network/torrent/torrent.pro b/examples/network/torrent/torrent.pro
index 16a44d8aad..c640c3b5d0 100644
--- a/examples/network/torrent/torrent.pro
+++ b/examples/network/torrent/torrent.pro
@@ -1,4 +1,5 @@
QT += network widgets
+requires(qtConfig(filedialog))
HEADERS += addtorrentdialog.h \
bencodeparser.h \
diff --git a/examples/network/torrent/torrentclient.cpp b/examples/network/torrent/torrentclient.cpp
index ba87924ff9..95232646ab 100644
--- a/examples/network/torrent/torrentclient.cpp
+++ b/examples/network/torrent/torrentclient.cpp
@@ -692,7 +692,7 @@ void TorrentClient::connectToPeers()
// Start as many connections as we can
while (!weighedPeers.isEmpty() && ConnectionManager::instance()->canAddConnection()
- && (qrand() % (ConnectionManager::instance()->maxConnections() / 2))) {
+ && (QRandomGenerator::global()->bounded(ConnectionManager::instance()->maxConnections() / 2))) {
PeerWireClient *client = new PeerWireClient(ConnectionManager::instance()->clientId(), this);
RateController::instance()->addSocket(client);
ConnectionManager::instance()->addConnection(client);
@@ -701,7 +701,7 @@ void TorrentClient::connectToPeers()
d->connections << client;
// Pick a random peer from the list of weighed peers.
- TorrentPeer *peer = weighedPeers.takeAt(qrand() % weighedPeers.size());
+ TorrentPeer *peer = weighedPeers.takeAt(QRandomGenerator::global()->bounded(weighedPeers.size()));
weighedPeers.removeAll(peer);
peer->connectStart = QDateTime::currentSecsSinceEpoch();
peer->lastVisited = peer->connectStart;
@@ -1114,7 +1114,7 @@ void TorrentClient::scheduleUploads()
}
if ((client->peerWireState() & PeerWireClient::ChokingPeer) == 0) {
- if ((qrand() % 10) == 0)
+ if ((QRandomGenerator::global()->bounded(10)) == 0)
client->abort();
else
client->chokePeer();
@@ -1128,7 +1128,7 @@ void TorrentClient::scheduleUploads()
// random peer to allow it to compete for a position among the
// downloaders. (This is known as an "optimistic unchoke".)
if (!allClients.isEmpty()) {
- PeerWireClient *client = allClients[qrand() % allClients.size()];
+ PeerWireClient *client = allClients[QRandomGenerator::global()->bounded(allClients.size())];
if (client->peerWireState() & PeerWireClient::ChokingPeer)
client->unchokePeer();
}
@@ -1189,7 +1189,7 @@ void TorrentClient::schedulePieceForClient(PeerWireClient *client)
piece = d->payloads.value(client);
if (!piece) {
QList<TorrentPiece *> values = d->pendingPieces.values();
- piece = values.value(qrand() % values.size());
+ piece = values.value(QRandomGenerator::global()->bounded(values.size()));
piece->inProgress = true;
d->payloads.insert(client, piece);
}
@@ -1246,14 +1246,14 @@ void TorrentClient::schedulePieceForClient(PeerWireClient *client)
++it;
}
if (!partialPieces.isEmpty())
- piece = partialPieces.value(qrand() % partialPieces.size());
+ piece = partialPieces.value(QRandomGenerator::global()->bounded(partialPieces.size()));
if (!piece) {
// Pick a random piece 3 out of 4 times; otherwise, pick either
// one of the most common or the least common pieces available,
// depending on the state we're in.
int pieceIndex = 0;
- if (d->state == WarmingUp || (qrand() & 4) == 0) {
+ if (d->state == WarmingUp || (QRandomGenerator::global()->generate() & 4) == 0) {
int *occurrences = new int[d->pieceCount];
memset(occurrences, 0, d->pieceCount * sizeof(int));
@@ -1293,7 +1293,7 @@ void TorrentClient::schedulePieceForClient(PeerWireClient *client)
}
// Select one piece randomly
- pieceIndex = piecesReadyForDownload.at(qrand() % piecesReadyForDownload.size());
+ pieceIndex = piecesReadyForDownload.at(QRandomGenerator::global()->bounded(piecesReadyForDownload.size()));
delete [] occurrences;
} else {
// Make up a list of available piece indices, and pick
@@ -1304,7 +1304,7 @@ void TorrentClient::schedulePieceForClient(PeerWireClient *client)
if (incompletePiecesAvailableToClient.testBit(i))
values << i;
}
- pieceIndex = values.at(qrand() % values.size());
+ pieceIndex = values.at(QRandomGenerator::global()->bounded(values.size()));
}
// Create a new TorrentPiece and fill in all initial
@@ -1396,8 +1396,8 @@ int TorrentClient::requestBlocks(PeerWireClient *client, TorrentPiece *piece, in
// speedup comes from an increased chance of receiving
// different blocks from the different peers.
for (int i = 0; i < bits.size(); ++i) {
- int a = qrand() % bits.size();
- int b = qrand() % bits.size();
+ int a = QRandomGenerator::global()->bounded(bits.size());
+ int b = QRandomGenerator::global()->bounded(bits.size());
int tmp = bits[a];
bits[a] = bits[b];
bits[b] = tmp;
diff --git a/examples/opengl/contextinfo/contextinfo.pro b/examples/opengl/contextinfo/contextinfo.pro
index 2836e5ea5a..3d948dd282 100644
--- a/examples/opengl/contextinfo/contextinfo.pro
+++ b/examples/opengl/contextinfo/contextinfo.pro
@@ -1,5 +1,6 @@
TEMPLATE = app
QT += widgets
+requires(qtConfig(filedialog))
SOURCES += main.cpp \
widget.cpp \
diff --git a/examples/opengl/hellowindow/hellowindow.cpp b/examples/opengl/hellowindow/hellowindow.cpp
index dc48cc4b76..a978e19b79 100644
--- a/examples/opengl/hellowindow/hellowindow.cpp
+++ b/examples/opengl/hellowindow/hellowindow.cpp
@@ -52,6 +52,7 @@
#include <QOpenGLContext>
#include <QOpenGLFunctions>
+#include <QRandomGenerator>
#include <qmath.h>
Renderer::Renderer(const QSurfaceFormat &format, Renderer *share, QScreen *screen)
@@ -68,9 +69,9 @@ Renderer::Renderer(const QSurfaceFormat &format, Renderer *share, QScreen *scree
m_context->create();
m_backgroundColor = QColor::fromRgbF(0.1f, 0.1f, 0.2f, 1.0f);
- m_backgroundColor.setRed(qrand() % 64);
- m_backgroundColor.setGreen(qrand() % 128);
- m_backgroundColor.setBlue(qrand() % 256);
+ m_backgroundColor.setRed(QRandomGenerator::global()->bounded(64));
+ m_backgroundColor.setGreen(QRandomGenerator::global()->bounded(128));
+ m_backgroundColor.setBlue(QRandomGenerator::global()->bounded(256));
}
HelloWindow::HelloWindow(const QSharedPointer<Renderer> &renderer, QScreen *screen)
@@ -93,6 +94,8 @@ HelloWindow::HelloWindow(const QSharedPointer<Renderer> &renderer, QScreen *scre
void HelloWindow::exposeEvent(QExposeEvent *)
{
m_renderer->setAnimating(this, isExposed());
+ if (isExposed())
+ m_renderer->render();
}
void HelloWindow::mousePressEvent(QMouseEvent *)
@@ -276,21 +279,20 @@ void Renderer::createGeometry()
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
- const qreal Pi = 3.14159f;
const int NumSectors = 100;
-
+ const qreal sectorAngle = 2 * qreal(M_PI) / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
- qreal angle1 = (i * 2 * Pi) / NumSectors;
- qreal x5 = 0.30 * qSin(angle1);
- qreal y5 = 0.30 * qCos(angle1);
- qreal x6 = 0.20 * qSin(angle1);
- qreal y6 = 0.20 * qCos(angle1);
-
- qreal angle2 = ((i + 1) * 2 * Pi) / NumSectors;
- qreal x7 = 0.20 * qSin(angle2);
- qreal y7 = 0.20 * qCos(angle2);
- qreal x8 = 0.30 * qSin(angle2);
- qreal y8 = 0.30 * qCos(angle2);
+ qreal angle = i * sectorAngle;
+ qreal x5 = 0.30 * qSin(angle);
+ qreal y5 = 0.30 * qCos(angle);
+ qreal x6 = 0.20 * qSin(angle);
+ qreal y6 = 0.20 * qCos(angle);
+
+ angle += sectorAngle;
+ qreal x7 = 0.20 * qSin(angle);
+ qreal y7 = 0.20 * qCos(angle);
+ qreal x8 = 0.30 * qSin(angle);
+ qreal y8 = 0.30 * qCos(angle);
quad(x5, y5, x6, y6, x7, y7, x8, y8);
diff --git a/examples/opengl/hellowindow/hellowindow.h b/examples/opengl/hellowindow/hellowindow.h
index 1372152e93..e92e45a125 100644
--- a/examples/opengl/hellowindow/hellowindow.h
+++ b/examples/opengl/hellowindow/hellowindow.h
@@ -70,7 +70,7 @@ public:
void setAnimating(HelloWindow *window, bool animating);
-private slots:
+public slots:
void render();
private:
diff --git a/examples/opengl/legacy/framebufferobject2/glwidget.cpp b/examples/opengl/legacy/framebufferobject2/glwidget.cpp
index ac8deddd1f..f14d31aff6 100644
--- a/examples/opengl/legacy/framebufferobject2/glwidget.cpp
+++ b/examples/opengl/legacy/framebufferobject2/glwidget.cpp
@@ -50,8 +50,7 @@
#include "glwidget.h"
#include <QtGui/QImage>
-
-#include <math.h>
+#include <qmath.h>
static GLint cubeArray[][3] = {
{0, 0, 0}, {0, 1, 0}, {1, 1, 0}, {1, 0, 0},
@@ -253,6 +252,6 @@ void GLWidget::drawCube(int i, GLfloat z, GLfloat rotation, GLfloat jmp, GLfloat
xOffs[i] = xOffs[i] > 1.0f ? 1.0f : -1.0f;
}
xOffs[i] += xInc[i];
- yOffs[i] = qAbs(cos((-3.141592f * jmp) * xOffs[i]) * amp) - 1;
+ yOffs[i] = qAbs(cos((-GLfloat(M_PI) * jmp) * xOffs[i]) * amp) - 1;
rot[i] += rotation;
}
diff --git a/examples/opengl/legacy/grabber/glwidget.cpp b/examples/opengl/legacy/grabber/glwidget.cpp
index 958b8055cd..6be4d30597 100644
--- a/examples/opengl/legacy/grabber/glwidget.cpp
+++ b/examples/opengl/legacy/grabber/glwidget.cpp
@@ -52,8 +52,7 @@
#include <QMouseEvent>
#include <QTimer>
-
-#include <math.h>
+#include <qmath.h>
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(parent)
@@ -190,8 +189,6 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
GLdouble outerRadius, GLdouble thickness,
GLdouble toothSize, GLint toothCount)
{
- const double Pi = 3.14159265358979323846;
-
GLuint list = glGenLists(1);
glNewList(list, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, reflectance);
@@ -199,7 +196,8 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
GLdouble r0 = innerRadius;
GLdouble r1 = outerRadius - toothSize / 2.0;
GLdouble r2 = outerRadius + toothSize / 2.0;
- GLdouble delta = (2.0 * Pi / toothCount) / 4.0;
+ GLdouble toothAngle = 2 * M_PI / toothCount;
+ GLdouble delta = toothAngle / 4.0;
GLdouble z = thickness / 2.0;
glShadeModel(GL_FLAT);
@@ -211,7 +209,7 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
glBegin(GL_QUAD_STRIP);
for (int j = 0; j <= toothCount; ++j) {
- GLdouble angle = 2.0 * Pi * j / toothCount;
+ GLdouble angle = j * toothAngle;
glVertex3d(r0 * cos(angle), r0 * sin(angle), sign * z);
glVertex3d(r1 * cos(angle), r1 * sin(angle), sign * z);
glVertex3d(r0 * cos(angle), r0 * sin(angle), sign * z);
@@ -221,7 +219,7 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
glBegin(GL_QUADS);
for (int j = 0; j < toothCount; ++j) {
- GLdouble angle = 2.0 * Pi * j / toothCount;
+ GLdouble angle = j * toothAngle;
glVertex3d(r1 * cos(angle), r1 * sin(angle), sign * z);
glVertex3d(r2 * cos(angle + delta), r2 * sin(angle + delta), sign * z);
glVertex3d(r2 * cos(angle + 2 * delta), r2 * sin(angle + 2 * delta), sign * z);
@@ -233,7 +231,7 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
glBegin(GL_QUAD_STRIP);
for (int i = 0; i < toothCount; ++i) {
for (int j = 0; j < 2; ++j) {
- GLdouble angle = 2.0 * Pi * (i + j / 2.0) / toothCount;
+ GLdouble angle = (i + j / 2.0) * toothAngle;
GLdouble s1 = r1;
GLdouble s2 = r2;
if (j == 1)
@@ -257,7 +255,7 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
glBegin(GL_QUAD_STRIP);
for (int i = 0; i <= toothCount; ++i) {
- GLdouble angle = i * 2.0 * Pi / toothCount;
+ GLdouble angle = i * toothAngle;
glNormal3d(-cos(angle), -sin(angle), 0.0);
glVertex3d(r0 * cos(angle), r0 * sin(angle), +z);
glVertex3d(r0 * cos(angle), r0 * sin(angle), -z);
diff --git a/examples/opengl/legacy/overpainting/bubble.cpp b/examples/opengl/legacy/overpainting/bubble.cpp
index afc50117d0..352e359cf9 100644
--- a/examples/opengl/legacy/overpainting/bubble.cpp
+++ b/examples/opengl/legacy/overpainting/bubble.cpp
@@ -50,6 +50,8 @@
#include "bubble.h"
+#include <QRandomGenerator>
+
Bubble::Bubble(const QPointF &position, qreal radius, const QPointF &velocity)
: position(position), vel(velocity), radius(radius)
{
@@ -80,10 +82,10 @@ void Bubble::drawBubble(QPainter *painter)
QColor Bubble::randomColor()
{
- int red = int(205 + 50.0*qrand()/(RAND_MAX+1.0));
- int green = int(205 + 50.0*qrand()/(RAND_MAX+1.0));
- int blue = int(205 + 50.0*qrand()/(RAND_MAX+1.0));
- int alpha = int(91 + 100.0*qrand()/(RAND_MAX+1.0));
+ int red = int(205 + QRandomGenerator::global()->bounded(50));
+ int green = int(205 + QRandomGenerator::global()->bounded(50));
+ int blue = int(205 + QRandomGenerator::global()->bounded(50));
+ int alpha = int(91 + QRandomGenerator::global()->bounded(100));
return QColor(red, green, blue, alpha);
}
diff --git a/examples/opengl/legacy/overpainting/glwidget.cpp b/examples/opengl/legacy/overpainting/glwidget.cpp
index 7e9f4a5beb..1ec7bd731c 100644
--- a/examples/opengl/legacy/overpainting/glwidget.cpp
+++ b/examples/opengl/legacy/overpainting/glwidget.cpp
@@ -53,6 +53,7 @@
#include "glwidget.h"
#include <QMouseEvent>
+#include <QRandomGenerator>
#include <QTime>
#include <math.h>
@@ -67,7 +68,6 @@ GLWidget::GLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
QTime midnight(0, 0, 0);
- qsrand(midnight.secsTo(QTime::currentTime()));
logo = 0;
xRot = 0;
@@ -234,11 +234,11 @@ QSize GLWidget::sizeHint() const
void GLWidget::createBubbles(int number)
{
for (int i = 0; i < number; ++i) {
- QPointF position(width()*(0.1 + (0.8*qrand()/(RAND_MAX+1.0))),
- height()*(0.1 + (0.8*qrand()/(RAND_MAX+1.0))));
- qreal radius = qMin(width(), height())*(0.0125 + 0.0875*qrand()/(RAND_MAX+1.0));
- QPointF velocity(width()*0.0125*(-0.5 + qrand()/(RAND_MAX+1.0)),
- height()*0.0125*(-0.5 + qrand()/(RAND_MAX+1.0)));
+ QPointF position(width()*(0.1 + QRandomGenerator::global()->bounded(0.8)),
+ height()*(0.1 + QRandomGenerator::global()->bounded(0.8)));
+ qreal radius = qMin(width(), height())*(0.0125 + QRandomGenerator::global()->bounded(0.0875));
+ QPointF velocity(width()*0.0125*(-0.5 + QRandomGenerator::global()->bounded(1.0)),
+ height()*0.0125*(-0.5 + QRandomGenerator::global()->bounded(1.0)));
bubbles.append(new Bubble(position, radius, velocity));
}
diff --git a/examples/opengl/legacy/pbuffers2/glwidget.cpp b/examples/opengl/legacy/pbuffers2/glwidget.cpp
index c99f9e40fa..c710d03cab 100644
--- a/examples/opengl/legacy/pbuffers2/glwidget.cpp
+++ b/examples/opengl/legacy/pbuffers2/glwidget.cpp
@@ -49,10 +49,9 @@
****************************************************************************/
#include <QtGui/QImage>
+#include <qmath.h>
#include "glwidget.h"
-#include <math.h>
-
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
@@ -291,8 +290,6 @@ void GLWidget::restoreGLState()
glPopAttrib();
}
-#define PI 3.14159
-
void GLWidget::timerEvent(QTimerEvent *)
{
if (QApplication::mouseButtons() != 0)
@@ -305,31 +302,27 @@ void GLWidget::timerEvent(QTimerEvent *)
else if (!scale_in && scale < .5f)
scale_in = true;
- scale = scale_in ? scale + scale*0.01f : scale-scale*0.01f;
+ scale *= scale_in ? 1.01f : 0.99f;
rot_z += 0.3f;
rot_x += 0.1f;
- int dx, dy; // disturbance point
- float s, v, W, t;
- int i, j;
- static float wt[128][128];
+ static float wt = 0.0;
+ wt += 0.1f;
+
const int width = logo.width();
+ const int dx = width >> 1, dy = dx; // disturbance point
+ const float v = -4; // wave speed
+ const float W = .3f;
const int AMP = 5;
- dx = dy = width >> 1;
-
- W = .3f;
- v = -4; // wave speed
-
- for (i = 0; i < width; ++i) {
- for ( j = 0; j < width; ++j) {
- s = sqrt((double) ((j - dx) * (j - dx) + (i - dy) * (i - dy)));
- wt[i][j] += 0.1f;
- t = s / v;
+ for (int i = 0; i < width; ++i) {
+ for (int j = 0; j < width; ++j) {
+ const float s = hypot(j - dx, i - dy);
+ const double raw = AMP * sin(2 * M_PI * W * (wt + s / v));
if (s != 0)
- wave[i*width + j] = AMP * sin(2 * PI * W * (wt[i][j] + t)) / (0.2*(s + 2));
+ wave[i * width + j] = raw / (0.2 * (s + 2));
else
- wave[i*width + j] = AMP * sin(2 * PI * W * (wt[i][j] + t));
+ wave[i * width + j] = raw;
}
}
}
diff --git a/examples/opengl/legacy/samplebuffers/glwidget.cpp b/examples/opengl/legacy/samplebuffers/glwidget.cpp
index 14c59c9143..da30de4d55 100644
--- a/examples/opengl/legacy/samplebuffers/glwidget.cpp
+++ b/examples/opengl/legacy/samplebuffers/glwidget.cpp
@@ -49,7 +49,7 @@
****************************************************************************/
#include "glwidget.h"
-#include <math.h>
+#include <qmath.h>
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
@@ -116,7 +116,6 @@ void GLWidget::timerEvent(QTimerEvent *)
void GLWidget::makeObject()
{
QColor qtGreen(QColor::fromCmykF(0.40, 0.0, 1.0, 0.0));
- const double Pi = 3.14159265358979323846;
const int NumSectors = 15;
GLdouble x1 = +0.06;
GLdouble y1 = -0.14;
@@ -130,18 +129,19 @@ void GLWidget::makeObject()
list = glGenLists(1);
glNewList(list, GL_COMPILE);
{
+ const double sectorAngle = 2 * M_PI / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
- double angle1 = (i * 2 * Pi) / NumSectors;
- GLdouble x5 = 0.30 * sin(angle1);
- GLdouble y5 = 0.30 * cos(angle1);
- GLdouble x6 = 0.20 * sin(angle1);
- GLdouble y6 = 0.20 * cos(angle1);
-
- double angle2 = ((i + 1) * 2 * Pi) / NumSectors;
- GLdouble x7 = 0.20 * sin(angle2);
- GLdouble y7 = 0.20 * cos(angle2);
- GLdouble x8 = 0.30 * sin(angle2);
- GLdouble y8 = 0.30 * cos(angle2);
+ double angle = i * sectorAngle;
+ GLdouble x5 = 0.30 * sin(angle);
+ GLdouble y5 = 0.30 * cos(angle);
+ GLdouble x6 = 0.20 * sin(angle);
+ GLdouble y6 = 0.20 * cos(angle);
+
+ angle += sectorAngle;
+ GLdouble x7 = 0.20 * sin(angle);
+ GLdouble y7 = 0.20 * cos(angle);
+ GLdouble x8 = 0.30 * sin(angle);
+ GLdouble y8 = 0.30 * cos(angle);
qglColor(qtGreen);
quad(GL_QUADS, x5, y5, x6, y6, x7, y7, x8, y8);
diff --git a/examples/opengl/qopenglwidget/bubble.cpp b/examples/opengl/qopenglwidget/bubble.cpp
index adf5742f6a..dbaf460f6f 100644
--- a/examples/opengl/qopenglwidget/bubble.cpp
+++ b/examples/opengl/qopenglwidget/bubble.cpp
@@ -109,10 +109,10 @@ void Bubble::drawBubble(QPainter *painter)
QColor Bubble::randomColor()
{
- int red = int(185 + 70.0*qrand()/(RAND_MAX+1.0));
- int green = int(185 + 70.0*qrand()/(RAND_MAX+1.0));
- int blue = int(205 + 50.0*qrand()/(RAND_MAX+1.0));
- int alpha = int(91 + 100.0*qrand()/(RAND_MAX+1.0));
+ int red = int(185 + QRandomGenerator::global()->bounded(70));
+ int green = int(185 + QRandomGenerator::global()->bounded(70));
+ int blue = int(205 + QRandomGenerator::global()->bounded(50));
+ int alpha = int(91 + QRandomGenerator::global()->bounded(100));
return QColor(red, green, blue, alpha);
}
diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp
index 21d922d713..3fe919f94b 100644
--- a/examples/opengl/qopenglwidget/glwidget.cpp
+++ b/examples/opengl/qopenglwidget/glwidget.cpp
@@ -53,14 +53,19 @@
#include <QPaintEngine>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
+#include <QRandomGenerator>
#include <QCoreApplication>
-#include <math.h>
+#include <qmath.h>
#include "mainwindow.h"
#include "bubble.h"
const int bubbleNum = 8;
+#ifndef GL_SRGB8_ALPHA8
+#define GL_SRGB8_ALPHA8 0x8C43
+#endif
+
GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
: m_mainWindow(mw),
m_showBubbles(true),
@@ -75,6 +80,8 @@ GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
m_background(background)
{
setMinimumSize(300, 250);
+ if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
+ setTextureFormat(GL_SRGB8_ALPHA8);
}
GLWidget::~GLWidget()
@@ -414,11 +421,11 @@ void GLWidget::paintGL()
void GLWidget::createBubbles(int number)
{
for (int i = 0; i < number; ++i) {
- QPointF position(width()*(0.1 + (0.8*qrand()/(RAND_MAX+1.0))),
- height()*(0.1 + (0.8*qrand()/(RAND_MAX+1.0))));
- qreal radius = qMin(width(), height())*(0.0175 + 0.0875*qrand()/(RAND_MAX+1.0));
- QPointF velocity(width()*0.0175*(-0.5 + qrand()/(RAND_MAX+1.0)),
- height()*0.0175*(-0.5 + qrand()/(RAND_MAX+1.0)));
+ QPointF position(width()*(0.1 + QRandomGenerator::global()->bounded(0.8)),
+ height()*(0.1 + QRandomGenerator::global()->bounded(0.8)));
+ qreal radius = qMin(width(), height())*(0.0175 + QRandomGenerator::global()->bounded(0.0875));
+ QPointF velocity(width()*0.0175*(-0.5 + QRandomGenerator::global()->bounded(1.0)),
+ height()*0.0175*(-0.5 + QRandomGenerator::global()->bounded(1.0)));
m_bubbles.append(new Bubble(position, radius, velocity));
}
@@ -449,21 +456,21 @@ void GLWidget::createGeometry()
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
- const qreal Pi = 3.14159f;
const int NumSectors = 100;
+ const qreal sectorAngle = 2 * qreal(M_PI) / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
- qreal angle1 = (i * 2 * Pi) / NumSectors;
- qreal x5 = 0.30 * sin(angle1);
- qreal y5 = 0.30 * cos(angle1);
- qreal x6 = 0.20 * sin(angle1);
- qreal y6 = 0.20 * cos(angle1);
-
- qreal angle2 = ((i + 1) * 2 * Pi) / NumSectors;
- qreal x7 = 0.20 * sin(angle2);
- qreal y7 = 0.20 * cos(angle2);
- qreal x8 = 0.30 * sin(angle2);
- qreal y8 = 0.30 * cos(angle2);
+ qreal angle = i * sectorAngle;
+ qreal x5 = 0.30 * sin(angle);
+ qreal y5 = 0.30 * cos(angle);
+ qreal x6 = 0.20 * sin(angle);
+ qreal y6 = 0.20 * cos(angle);
+
+ angle += sectorAngle;
+ qreal x7 = 0.20 * sin(angle);
+ qreal y7 = 0.20 * cos(angle);
+ qreal x8 = 0.30 * sin(angle);
+ qreal y8 = 0.30 * cos(angle);
quad(x5, y5, x6, y6, x7, y7, x8, y8);
diff --git a/examples/opengl/qopenglwidget/main.cpp b/examples/opengl/qopenglwidget/main.cpp
index ea90dca62f..42fc772445 100644
--- a/examples/opengl/qopenglwidget/main.cpp
+++ b/examples/opengl/qopenglwidget/main.cpp
@@ -69,11 +69,15 @@ int main( int argc, char ** argv )
parser.addVersionOption();
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
parser.addOption(multipleSampleOption);
+ QCommandLineOption srgbOption("srgb", "Use sRGB Color Space");
+ parser.addOption(srgbOption);
parser.process(a);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
+ if (parser.isSet(srgbOption))
+ format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
if (parser.isSet(multipleSampleOption))
format.setSamples(4);
QSurfaceFormat::setDefaultFormat(format);
diff --git a/examples/opengl/qopenglwidget/mainwindow.cpp b/examples/opengl/qopenglwidget/mainwindow.cpp
index 1bb2aa2bf0..4bd123628f 100644
--- a/examples/opengl/qopenglwidget/mainwindow.cpp
+++ b/examples/opengl/qopenglwidget/mainwindow.cpp
@@ -56,6 +56,7 @@
#include <QSlider>
#include <QLabel>
#include <QCheckBox>
+#include <QRandomGenerator>
#include <QSpinBox>
#include <QScrollArea>
@@ -155,7 +156,9 @@ void MainWindow::addNew()
{
if (m_nextY == 4)
return;
- GLWidget *w = new GLWidget(this, false, qRgb(qrand() % 256, qrand() % 256, qrand() % 256));
+ GLWidget *w = new GLWidget(this, false, qRgb(QRandomGenerator::global()->bounded(256),
+ QRandomGenerator::global()->bounded(256),
+ QRandomGenerator::global()->bounded(256)));
m_glWidgets << w;
connect(m_timer, &QTimer::timeout, w, QOverload<>::of(&QWidget::update));
m_layout->addWidget(w, m_nextY, m_nextX, 1, 1);
diff --git a/examples/opengl/qopenglwindow/background.frag b/examples/opengl/qopenglwindow/background.frag
index eecb6d3120..4af85aae8e 100644
--- a/examples/opengl/qopenglwindow/background.frag
+++ b/examples/opengl/qopenglwindow/background.frag
@@ -1,4 +1,4 @@
-#define M_PI 3.1415926535897932384626433832795
+#define M_PI 3.14159265358979323846
#define SPEED 10000.0
uniform int currentTime;
diff --git a/examples/opengl/threadedqopenglwidget/glwidget.cpp b/examples/opengl/threadedqopenglwidget/glwidget.cpp
index f9738db2e5..cc528a734a 100644
--- a/examples/opengl/threadedqopenglwidget/glwidget.cpp
+++ b/examples/opengl/threadedqopenglwidget/glwidget.cpp
@@ -49,7 +49,7 @@
****************************************************************************/
#include "glwidget.h"
-#include <math.h>
+#include <qmath.h>
#include <QGuiApplication>
GLWidget::GLWidget(QWidget *parent)
@@ -282,21 +282,21 @@ void Renderer::createGeometry()
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
- const qreal Pi = 3.14159f;
const int NumSectors = 100;
+ const qreal sectorAngle = 2 * qreal(M_PI) / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
- qreal angle1 = (i * 2 * Pi) / NumSectors;
- qreal x5 = 0.30 * sin(angle1);
- qreal y5 = 0.30 * cos(angle1);
- qreal x6 = 0.20 * sin(angle1);
- qreal y6 = 0.20 * cos(angle1);
-
- qreal angle2 = ((i + 1) * 2 * Pi) / NumSectors;
- qreal x7 = 0.20 * sin(angle2);
- qreal y7 = 0.20 * cos(angle2);
- qreal x8 = 0.30 * sin(angle2);
- qreal y8 = 0.30 * cos(angle2);
+ qreal angle = i * sectorAngle;
+ qreal x5 = 0.30 * sin(angle);
+ qreal y5 = 0.30 * cos(angle);
+ qreal x6 = 0.20 * sin(angle);
+ qreal y6 = 0.20 * cos(angle);
+
+ angle += sectorAngle;
+ qreal x7 = 0.20 * sin(angle);
+ qreal y7 = 0.20 * cos(angle);
+ qreal x8 = 0.30 * sin(angle);
+ qreal y8 = 0.30 * cos(angle);
quad(x5, y5, x6, y6, x7, y7, x8, y8);
diff --git a/examples/qtconcurrent/imagescaling/imagescaling.pro b/examples/qtconcurrent/imagescaling/imagescaling.pro
index 110f8f1b0b..127fa532c9 100644
--- a/examples/qtconcurrent/imagescaling/imagescaling.pro
+++ b/examples/qtconcurrent/imagescaling/imagescaling.pro
@@ -1,4 +1,5 @@
QT += concurrent widgets
+requires(qtConfig(filedialog))
SOURCES += main.cpp imagescaling.cpp
HEADERS += imagescaling.h
diff --git a/examples/sql/books/books.pro b/examples/sql/books/books.pro
index 2b3d541fe8..870e4a6c00 100644
--- a/examples/sql/books/books.pro
+++ b/examples/sql/books/books.pro
@@ -7,6 +7,7 @@ SOURCES = bookdelegate.cpp main.cpp bookwindow.cpp
FORMS = bookwindow.ui
QT += sql widgets widgets
+requires(qtConfig(tableview))
target.path = $$[QT_INSTALL_EXAMPLES]/sql/books
INSTALLS += target
diff --git a/examples/sql/cachedtable/cachedtable.pro b/examples/sql/cachedtable/cachedtable.pro
index 74f83bbec7..e9bcaa00d4 100644
--- a/examples/sql/cachedtable/cachedtable.pro
+++ b/examples/sql/cachedtable/cachedtable.pro
@@ -3,6 +3,7 @@ HEADERS = ../connection.h \
SOURCES = main.cpp \
tableeditor.cpp
QT += sql widgets
+requires(qtConfig(tableview))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/sql/cachedtable
diff --git a/examples/sql/doc/src/drilldown.qdoc b/examples/sql/doc/src/drilldown.qdoc
index e8841d2013..7a8aa2037a 100644
--- a/examples/sql/doc/src/drilldown.qdoc
+++ b/examples/sql/doc/src/drilldown.qdoc
@@ -163,7 +163,7 @@
submitted to the database until the user expliclity requests a
submit (the alternative is QDataWidgetMapper::AutoSubmit,
automatically submitting changes when the corresponding widget
- looses focus). Finally, we specify the item delegate the mapper
+ loses focus). Finally, we specify the item delegate the mapper
view should use for its items. The QSqlRelationalDelegate class
represents a delegate that unlike the default delegate, enables
combobox functionality for fields that are foreign keys into other
diff --git a/examples/sql/drilldown/drilldown.pro b/examples/sql/drilldown/drilldown.pro
index ef286bbf25..086e12ce35 100644
--- a/examples/sql/drilldown/drilldown.pro
+++ b/examples/sql/drilldown/drilldown.pro
@@ -8,6 +8,7 @@ SOURCES = imageitem.cpp \
main.cpp \
view.cpp
QT += sql widgets
+requires(qtConfig(combobox))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/sql/drilldown
diff --git a/examples/sql/masterdetail/masterdetail.pro b/examples/sql/masterdetail/masterdetail.pro
index 6f02aa0270..74050ceb20 100644
--- a/examples/sql/masterdetail/masterdetail.pro
+++ b/examples/sql/masterdetail/masterdetail.pro
@@ -8,6 +8,7 @@ SOURCES = dialog.cpp \
QT += sql widgets
QT += xml widgets
+requires(qtConfig(tableview))
EXAMPLE_FILES = albumdetails.xml
diff --git a/examples/sql/querymodel/querymodel.pro b/examples/sql/querymodel/querymodel.pro
index 498c14e4dc..79b61e8649 100644
--- a/examples/sql/querymodel/querymodel.pro
+++ b/examples/sql/querymodel/querymodel.pro
@@ -5,6 +5,7 @@ SOURCES = customsqlmodel.cpp \
editablesqlmodel.cpp \
main.cpp
QT += sql widgets
+requires(qtConfig(tableview))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/sql/querymodel
diff --git a/examples/sql/relationaltablemodel/relationaltablemodel.pro b/examples/sql/relationaltablemodel/relationaltablemodel.pro
index 677f5d886c..8ed5ee3bf1 100644
--- a/examples/sql/relationaltablemodel/relationaltablemodel.pro
+++ b/examples/sql/relationaltablemodel/relationaltablemodel.pro
@@ -1,6 +1,7 @@
HEADERS = ../connection.h
SOURCES = relationaltablemodel.cpp
QT += sql widgets
+requires(qtConfig(tableview))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/sql/relationaltablemodel
diff --git a/examples/sql/sqlbrowser/sqlbrowser.pro b/examples/sql/sqlbrowser/sqlbrowser.pro
index 1cc13d754f..47174c5725 100644
--- a/examples/sql/sqlbrowser/sqlbrowser.pro
+++ b/examples/sql/sqlbrowser/sqlbrowser.pro
@@ -2,6 +2,7 @@ TEMPLATE = app
TARGET = sqlbrowser
QT += sql widgets
+requires(qtConfig(tableview))
HEADERS = browser.h connectionwidget.h qsqlconnectiondialog.h
SOURCES = main.cpp browser.cpp connectionwidget.cpp qsqlconnectiondialog.cpp
diff --git a/examples/sql/sqlwidgetmapper/sqlwidgetmapper.pro b/examples/sql/sqlwidgetmapper/sqlwidgetmapper.pro
index fe600a9124..48820bc3b3 100644
--- a/examples/sql/sqlwidgetmapper/sqlwidgetmapper.pro
+++ b/examples/sql/sqlwidgetmapper/sqlwidgetmapper.pro
@@ -2,6 +2,7 @@ HEADERS = window.h
SOURCES = main.cpp \
window.cpp
QT += sql widgets
+requires(qtConfig(combobox))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/sql/sqlwidgetmapper
diff --git a/examples/sql/tablemodel/tablemodel.pro b/examples/sql/tablemodel/tablemodel.pro
index ab339f26d2..af2816d48b 100644
--- a/examples/sql/tablemodel/tablemodel.pro
+++ b/examples/sql/tablemodel/tablemodel.pro
@@ -1,6 +1,7 @@
HEADERS = ../connection.h
SOURCES = tablemodel.cpp
QT += sql widgets
+requires(qtConfig(tableview))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/sql/tablemodel
diff --git a/examples/touch/fingerpaint/fingerpaint.pro b/examples/touch/fingerpaint/fingerpaint.pro
index 97a2689501..f196f7eed4 100644
--- a/examples/touch/fingerpaint/fingerpaint.pro
+++ b/examples/touch/fingerpaint/fingerpaint.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
qtHaveModule(printsupport): QT += printsupport
HEADERS = mainwindow.h \
diff --git a/examples/touch/pinchzoom/main.cpp b/examples/touch/pinchzoom/main.cpp
index 67099618c7..938432600f 100644
--- a/examples/touch/pinchzoom/main.cpp
+++ b/examples/touch/pinchzoom/main.cpp
@@ -61,7 +61,6 @@ static const int MouseCount = 7;
int main(int argc, char **argv)
{
QApplication app(argc, argv);
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
//! [0]
//! [1]
diff --git a/examples/touch/pinchzoom/mouse.cpp b/examples/touch/pinchzoom/mouse.cpp
index f063e96654..1e6814be13 100644
--- a/examples/touch/pinchzoom/mouse.cpp
+++ b/examples/touch/pinchzoom/mouse.cpp
@@ -52,12 +52,12 @@
#include <QGraphicsScene>
#include <QPainter>
+#include <QRandomGenerator>
#include <QStyleOption>
+#include <qmath.h>
-#include <math.h>
-
-static const double Pi = 3.14159265358979323846264338327950288419717;
-static double TwoPi = 2.0 * Pi;
+const qreal Pi = M_PI;
+const qreal TwoPi = 2 * M_PI;
static qreal normalizeAngle(qreal angle)
{
@@ -71,9 +71,9 @@ static qreal normalizeAngle(qreal angle)
//! [0]
Mouse::Mouse()
: angle(0), speed(0), mouseEyeDirection(0),
- color(qrand() % 256, qrand() % 256, qrand() % 256)
+ color(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256))
{
- setTransform(QTransform().rotate(qrand() % (360 * 16)), true);
+ setTransform(QTransform().rotate(QRandomGenerator::global()->bounded(360 * 16)), true);
startTimer(1000 / 33);
}
//! [0]
@@ -139,9 +139,7 @@ void Mouse::timerEvent(QTimerEvent *)
//! [5]
QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
if (lineToCenter.length() > 150) {
- qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
- if (lineToCenter.dy() < 0)
- angleToCenter = TwoPi - angleToCenter;
+ qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx());
angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
if (angleToCenter < Pi && angleToCenter > Pi / 4) {
@@ -170,9 +168,7 @@ void Mouse::timerEvent(QTimerEvent *)
continue;
QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
- qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
- if (lineToMouse.dy() < 0)
- angleToMouse = TwoPi - angleToMouse;
+ qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx());
angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
@@ -189,16 +185,16 @@ void Mouse::timerEvent(QTimerEvent *)
// Add some random movement
//! [10]
- if (dangerMice.size() > 1 && (qrand() % 10) == 0) {
- if (qrand() % 1)
- angle += (qrand() % 100) / 500.0;
+ if (dangerMice.size() > 1 && QRandomGenerator::global()->bounded(10) == 0) {
+ if (QRandomGenerator::global()->bounded(1))
+ angle += QRandomGenerator::global()->bounded(1 / 500.0);
else
- angle -= (qrand() % 100) / 500.0;
+ angle -= QRandomGenerator::global()->bounded(1 / 500.0);
}
//! [10]
//! [11]
- speed += (-50 + qrand() % 100) / 100.0;
+ speed += (-50 + QRandomGenerator::global()->bounded(100)) / 100.0;
qreal dx = ::sin(angle) * 10;
mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5;
diff --git a/examples/vulkan/doc/images/hellovulkancubes.png b/examples/vulkan/doc/images/hellovulkancubes.png
new file mode 100644
index 0000000000..c3d819c047
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkancubes.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkantexture.png b/examples/vulkan/doc/images/hellovulkantexture.png
new file mode 100644
index 0000000000..0cb47a70be
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkantexture.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkantriangle.png b/examples/vulkan/doc/images/hellovulkantriangle.png
new file mode 100644
index 0000000000..f88b27a873
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkantriangle.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkanwidget.png b/examples/vulkan/doc/images/hellovulkanwidget.png
new file mode 100644
index 0000000000..b85d4dc596
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkanwidget.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkanwindow.png b/examples/vulkan/doc/images/hellovulkanwindow.png
new file mode 100644
index 0000000000..c55029312c
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkanwindow.png
Binary files differ
diff --git a/examples/vulkan/doc/src/hellovulkancubes.qdoc b/examples/vulkan/doc/src/hellovulkancubes.qdoc
new file mode 100644
index 0000000000..934d2015a1
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkancubes.qdoc
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkancubes
+ \title Hello Vulkan Cubes Example
+ \ingroup examples-vulkan
+ \brief Shows the basics of using QVulkanWindow
+
+ The \e{Hello Vulkan Cubes Example} shows more advanced usage of QVulkanWindow.
+
+ \image hellovulkancubes.png
+
+ In this example there is a mesh loaded from a file and two different
+ materials and corresponding graphics pipelines. The rounded cubes are drawn
+ using instancing and feature a Phong lighting model with a single
+ directional light.
+
+ Unlike hellovulkantexture and hellovulkantriangle, the uniform buffer
+ handling takes an alternative approach here: dynamic uniform buffers are
+ used instead of multiple descriptor sets.
+
+ The example requires QtConcurrent since it demonstrates simple usage of
+ QtConcurrent::run(), QFuture, and QFutureWatcher in combination of
+ QVulkanWindow. Mesh and shader data loading, the potentially expensive
+ graphics pipeline construction, and the building of the frame command buffer
+ are all done in separate worker threads.
+
+ The scene is embedded into a widget-based user interface. The QVulkanWindow
+ subclass handles mouse and keyboard input as well since it provides a
+ first-person style camera in order to allow moving around in the scene.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/widgets/doc/src/configdialog.qdoc b/examples/vulkan/doc/src/hellovulkantexture.qdoc
index 9f2cc21adb..d0e0ca90a8 100644
--- a/examples/widgets/doc/src/configdialog.qdoc
+++ b/examples/vulkan/doc/src/hellovulkantexture.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -26,12 +26,16 @@
****************************************************************************/
/*!
- \example dialogs/configdialog
- \title Config Dialog Example
- \ingroup examples-dialogs
+ \example hellovulkantexture
+ \ingroup examples-vulkan
+ \title Hello Vulkan Texture Vulkan Example
+ \brief Shows the basics of rendering with textures in a QVulkanWindow
- \brief The Config Dialog examples shows how a configuration dialog can be created by
- using an icon view with a stacked widget.
+ The \e{Hello Vulkan Texture Example} builds on \l hellovulkantriangle. Here
+ instead of drawing a single triangle, a triangle strip is drawn in order to
+ get a quad on the screen. This is then textured using a QImage loaded from
+ a .png image file.
- \image configdialog-example.png
+ \image hellovulkantexture.png
+ \include examples-run.qdocinc
*/
diff --git a/examples/widgets/doc/src/lighting.qdoc b/examples/vulkan/doc/src/hellovulkantriangle.qdoc
index 994172cf5d..81af776ea1 100644
--- a/examples/widgets/doc/src/lighting.qdoc
+++ b/examples/vulkan/doc/src/hellovulkantriangle.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -26,10 +26,24 @@
****************************************************************************/
/*!
- \example effects/lighting
- \title Lighting Effect Example
- \ingroup examples-graphicsview-graphicseffects
- \brief Demonstrates how to apply effects on items in the view
+ \example hellovulkantriangle
+ \ingroup examples-vulkan
+ \title Hello Vulkan Triangle Example
+ \brief Shows the basics of rendering with QVulkanWindow and the Vulkan API
- \image lightingeffect-example.png
+ The \e{Hello Vulkan Triangle Example} builds on \l hellovulkanwindow. This
+ time a full graphics pipeline is created, including a vertex and fragment
+ shader. This pipeline is then used to render a triangle.
+
+ \image hellovulkantriangle.png
+
+ The example also demonstrates multisample antialiasing. Based on the
+ supported sample counts reported by QVulkanWindow::supportedSampleCounts()
+ the example chooses between 8x, 4x, or no multisampling. Once configured
+ via QVulkanWindow::setSamples(), QVulkanWindow takes care of the rest: the
+ additional multisample color buffers are created automatically, and
+ resolving into the swapchain buffers is performed at the end of the default
+ render pass for each frame.
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/widgets/doc/src/appchooser.qdoc b/examples/vulkan/doc/src/hellovulkanwidget.qdoc
index e74860214a..7987bdeff9 100644
--- a/examples/widgets/doc/src/appchooser.qdoc
+++ b/examples/vulkan/doc/src/hellovulkanwidget.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -26,13 +26,24 @@
****************************************************************************/
/*!
- \example animation/appchooser
- \title Application Chooser Example
+ \example hellovulkanwidget
+ \ingroup examples-vulkan
+ \title Hello Vulkan Widget Example
+ \brief Shows the usage of QVulkanWindow in QWidget applications
- \brief The Application Chooser example shows how to use the Qt state
- machine and the animation framework to select between
- applications.
+ The \e{Hello Vulkan Widget Example} is a variant of \l hellovulkantriangle
+ that embeds the QVulkanWindow into a QWidget-based user interface using
+ QWidget::createWindowContainer().
- \image appchooser-example.png
+ \image hellovulkanwidget.png
+ The code to set up the Vulkan pipeline and render the triangle is the same
+ as in \l hellovulkantriangle. In addition, this example demonstrates
+ another feature of QVulkanWindow: reading the image content back from the
+ color buffer into a QImage. By clicking the Grab button, the example
+ renders the next frame and follows it up with a transfer operation in order
+ to get the swapchain color buffer content copied into host accessible
+ memory. The image is then saved to disk via QImage::save().
+
+ \include examples-run.qdocinc
*/
diff --git a/examples/vulkan/doc/src/hellovulkanwindow.qdoc b/examples/vulkan/doc/src/hellovulkanwindow.qdoc
new file mode 100644
index 0000000000..06cc9c1c28
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkanwindow.qdoc
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkanwindow
+ \title Hello Vulkan Window Example
+ \ingroup examples-vulkan
+ \brief Shows the basics of using QVulkanWindow
+
+ The \e{Hello Vulkan Window Example} shows the basics of using QVulkanWindow
+ in order to display rendering with the Vulkan graphics API on systems that
+ support this.
+
+ \image hellovulkanwindow.png
+
+ In this example there will be no actual rendering: it simply begins and
+ ends a render pass, which results in clearing the buffers to a fixed value.
+ The color buffer clear value changes on every frame.
+
+ \section1 Startup
+
+ Each Qt application using Vulkan will have to have a \c{Vulkan instance}
+ which encapsulates application-level state and initializes a Vulkan library.
+
+ A QVulkanWindow must always be associated with a QVulkanInstance and hence
+ the example performs instance creation before the window. The
+ QVulkanInstance object must also outlive the window.
+
+ \snippet hellovulkanwindow/main.cpp 0
+
+ The example enables validation layers, when supported. When the requested
+ layers are not present, the request will be ignored. Additional layers and
+ extensions can be enabled in a similar manner.
+
+ \snippet hellovulkanwindow/main.cpp 1
+
+ Once the instance is ready, it is time to create a window. Note that \c w
+ lives on the stack and is declared after \c inst.
+
+ \section1 The QVulkanWindow Subclass
+
+ To add custom functionality to a QVulkanWindow, subclassing is used. This
+ follows the existing patterns from QOpenGLWindow and QOpenGLWidget.
+ However, QVulkanWindow utilizes a separate QVulkanWindowRenderer object.
+ This resembles QQuickFramebufferObject, and allows better separation of the
+ functions that are supposed to be reimplemented.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.h 0
+
+ The QVulkanWindow subclass reimplements the factory function
+ QVulkanWindow::createRenderer(). This simply returns a new instance of the
+ QVulkanWindowRenderer subclass. In order to be able to access various
+ Vulkan resources via the window object, a pointer to the window is passed
+ and stored via the constructor.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 0
+
+ Graphics resource creation and destruction is typically done in one of the
+ init - resource functions.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 1
+
+ \section1 The Actual Rendering
+
+ QVulkanWindow subclasses queue their draw calls in their reimplementation
+ of QVulkanWindowRenderer::startNextFrame(). Once done, they are required to
+ call back QVulkanWindow::frameReady(). The example has no asynchronous
+ command generation, so the frameReady() call is made directly from
+ startNextFrame().
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 2
+
+ To get continuous updates, the example simply invokes
+ QWindow::requestUpdate() in order to schedule a repaint.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/hellovulkancubes/camera.cpp b/examples/vulkan/hellovulkancubes/camera.cpp
new file mode 100644
index 0000000000..64dee03154
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/camera.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "camera.h"
+
+Camera::Camera(const QVector3D &pos)
+ : m_forward(0.0f, 0.0f, -1.0f),
+ m_right(1.0f, 0.0f, 0.0f),
+ m_up(0.0f, 1.0f, 0.0f),
+ m_pos(pos),
+ m_yaw(0.0f),
+ m_pitch(0.0f)
+{
+}
+
+static inline void clamp360(float *v)
+{
+ if (*v > 360.0f)
+ *v -= 360.0f;
+ if (*v < -360.0f)
+ *v += 360.0f;
+}
+
+void Camera::yaw(float degrees)
+{
+ m_yaw += degrees;
+ clamp360(&m_yaw);
+ m_yawMatrix.setToIdentity();
+ m_yawMatrix.rotate(m_yaw, 0, 1, 0);
+
+ QMatrix4x4 rotMat = m_pitchMatrix * m_yawMatrix;
+ m_forward = (QVector4D(0.0f, 0.0f, -1.0f, 0.0f) * rotMat).toVector3D();
+ m_right = (QVector4D(1.0f, 0.0f, 0.0f, 0.0f) * rotMat).toVector3D();
+}
+
+void Camera::pitch(float degrees)
+{
+ m_pitch += degrees;
+ clamp360(&m_pitch);
+ m_pitchMatrix.setToIdentity();
+ m_pitchMatrix.rotate(m_pitch, 1, 0, 0);
+
+ QMatrix4x4 rotMat = m_pitchMatrix * m_yawMatrix;
+ m_forward = (QVector4D(0.0f, 0.0f, -1.0f, 0.0f) * rotMat).toVector3D();
+ m_up = (QVector4D(0.0f, 1.0f, 0.0f, 0.0f) * rotMat).toVector3D();
+}
+
+void Camera::walk(float amount)
+{
+ m_pos[0] += amount * m_forward.x();
+ m_pos[2] += amount * m_forward.z();
+}
+
+void Camera::strafe(float amount)
+{
+ m_pos[0] += amount * m_right.x();
+ m_pos[2] += amount * m_right.z();
+}
+
+QMatrix4x4 Camera::viewMatrix() const
+{
+ QMatrix4x4 m = m_pitchMatrix * m_yawMatrix;
+ m.translate(-m_pos);
+ return m;
+}
diff --git a/examples/widgets/effects/lighting/lighting.h b/examples/vulkan/hellovulkancubes/camera.h
index 615824d46f..c5c579f066 100644
--- a/examples/widgets/effects/lighting/lighting.h
+++ b/examples/vulkan/hellovulkancubes/camera.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,33 +48,33 @@
**
****************************************************************************/
-#ifndef LIGHTING_H
-#define LIGHTING_H
+#ifndef CAMERA_H
+#define CAMERA_H
-#include <QGraphicsEffect>
-#include <QGraphicsView>
+#include <QVector3D>
+#include <QMatrix4x4>
-class Lighting: public QGraphicsView
+class Camera
{
- Q_OBJECT
-
public:
- Lighting(QWidget *parent = 0);
-
-private slots:
- void animate();
+ Camera(const QVector3D &pos);
-private:
- void setupScene();
+ void yaw(float degrees);
+ void pitch(float degrees);
+ void walk(float amount);
+ void strafe(float amount);
-protected:
- void resizeEvent(QResizeEvent *event) override;
+ QMatrix4x4 viewMatrix() const;
private:
- qreal angle;
- QGraphicsScene m_scene;
- QGraphicsItem *m_lightSource;
- QList<QGraphicsItem*> m_items;
+ QVector3D m_forward;
+ QVector3D m_right;
+ QVector3D m_up;
+ QVector3D m_pos;
+ float m_yaw;
+ float m_pitch;
+ QMatrix4x4 m_yawMatrix;
+ QMatrix4x4 m_pitchMatrix;
};
-#endif // LIGHTING_H
+#endif
diff --git a/examples/vulkan/hellovulkancubes/color.frag b/examples/vulkan/hellovulkancubes/color.frag
new file mode 100644
index 0000000000..3b04955963
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color.frag
@@ -0,0 +1,12 @@
+#version 440
+
+layout(push_constant) uniform PC {
+ layout(offset = 64) vec3 color;
+} pc;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(pc.color, 1.0);
+}
diff --git a/examples/vulkan/hellovulkancubes/color.vert b/examples/vulkan/hellovulkancubes/color.vert
new file mode 100644
index 0000000000..19bf815819
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color.vert
@@ -0,0 +1,14 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+layout(push_constant) uniform PC {
+ mat4 mvp;
+} pc;
+
+void main()
+{
+ gl_Position = pc.mvp * position;
+}
diff --git a/examples/vulkan/hellovulkancubes/color_frag.spv b/examples/vulkan/hellovulkancubes/color_frag.spv
new file mode 100644
index 0000000000..bd72984ffe
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_phong.frag b/examples/vulkan/hellovulkancubes/color_phong.frag
new file mode 100644
index 0000000000..8b0c715f3b
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong.frag
@@ -0,0 +1,39 @@
+#version 440
+
+layout(location = 0) in vec3 vECVertNormal;
+layout(location = 1) in vec3 vECVertPos;
+layout(location = 2) flat in vec3 vDiffuseAdjust;
+
+layout(std140, binding = 1) uniform buf {
+ vec3 ECCameraPosition;
+ vec3 ka;
+ vec3 kd;
+ vec3 ks;
+ // Have one light only for now.
+ vec3 ECLightPosition;
+ vec3 attenuation;
+ vec3 color;
+ float intensity;
+ float specularExp;
+} ubuf;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ vec3 unnormL = ubuf.ECLightPosition - vECVertPos;
+ float dist = length(unnormL);
+ float att = 1.0 / (ubuf.attenuation.x + ubuf.attenuation.y * dist + ubuf.attenuation.z * dist * dist);
+
+ vec3 N = normalize(vECVertNormal);
+ vec3 L = normalize(unnormL);
+ float NL = max(0.0, dot(N, L));
+ vec3 dColor = att * ubuf.intensity * ubuf.color * NL;
+
+ vec3 R = reflect(-L, N);
+ vec3 V = normalize(ubuf.ECCameraPosition - vECVertPos);
+ float RV = max(0.0, dot(R, V));
+ vec3 sColor = att * ubuf.intensity * ubuf.color * pow(RV, ubuf.specularExp);
+
+ fragColor = vec4(ubuf.ka + (ubuf.kd + vDiffuseAdjust) * dColor + ubuf.ks * sColor, 1.0);
+}
diff --git a/examples/vulkan/hellovulkancubes/color_phong.vert b/examples/vulkan/hellovulkancubes/color_phong.vert
new file mode 100644
index 0000000000..a1d1552685
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong.vert
@@ -0,0 +1,32 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 normal;
+
+// Instanced attributes to variate the translation of the model and the diffuse
+// color of the material.
+layout(location = 2) in vec3 instTranslate;
+layout(location = 3) in vec3 instDiffuseAdjust;
+
+out gl_PerVertex { vec4 gl_Position; };
+layout(location = 0) out vec3 vECVertNormal;
+layout(location = 1) out vec3 vECVertPos;
+layout(location = 2) flat out vec3 vDiffuseAdjust;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 vp;
+ mat4 model;
+ mat3 modelNormal;
+} ubuf;
+
+void main()
+{
+ vECVertNormal = normalize(ubuf.modelNormal * normal);
+ mat4 t = mat4(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ instTranslate.x, instTranslate.y, instTranslate.z, 1);
+ vECVertPos = vec3(t * ubuf.model * position);
+ vDiffuseAdjust = instDiffuseAdjust;
+ gl_Position = ubuf.vp * t * ubuf.model * position;
+}
diff --git a/examples/vulkan/hellovulkancubes/color_phong_frag.spv b/examples/vulkan/hellovulkancubes/color_phong_frag.spv
new file mode 100644
index 0000000000..a1a413533b
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_phong_vert.spv b/examples/vulkan/hellovulkancubes/color_phong_vert.spv
new file mode 100644
index 0000000000..3ede21e007
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_vert.spv b/examples/vulkan/hellovulkancubes/color_vert.spv
new file mode 100644
index 0000000000..3f708b7d07
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/hellovulkancubes.pro b/examples/vulkan/hellovulkancubes/hellovulkancubes.pro
new file mode 100644
index 0000000000..f9a9c3cff1
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/hellovulkancubes.pro
@@ -0,0 +1,24 @@
+QT += widgets concurrent
+
+HEADERS += \
+ mainwindow.h \
+ vulkanwindow.h \
+ renderer.h \
+ mesh.h \
+ shader.h \
+ camera.h
+
+SOURCES += \
+ main.cpp \
+ mainwindow.cpp \
+ vulkanwindow.cpp \
+ renderer.cpp \
+ mesh.cpp \
+ shader.cpp \
+ camera.cpp
+
+RESOURCES += hellovulkancubes.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkancubes
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc b/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc
new file mode 100644
index 0000000000..7b085e1875
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc
@@ -0,0 +1,10 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="block.buf">../shared/block.buf</file>
+ <file alias="qt_logo.buf">../shared/qt_logo.buf</file>
+ <file>color_phong_vert.spv</file>
+ <file>color_phong_frag.spv</file>
+ <file>color_vert.spv</file>
+ <file>color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkancubes/main.cpp b/examples/vulkan/hellovulkancubes/main.cpp
new file mode 100644
index 0000000000..4ec4d48645
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/main.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QLoggingCategory>
+#include "mainwindow.h"
+#include "vulkanwindow.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ const bool dbg = qEnvironmentVariableIntValue("QT_VK_DEBUG");
+
+ QVulkanInstance inst;
+
+ if (dbg) {
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+ }
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow *vulkanWindow = new VulkanWindow(dbg);
+ vulkanWindow->setVulkanInstance(&inst);
+
+ MainWindow mainWindow(vulkanWindow);
+ mainWindow.resize(1024, 768);
+ mainWindow.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkancubes/mainwindow.cpp b/examples/vulkan/hellovulkancubes/mainwindow.cpp
new file mode 100644
index 0000000000..2be7d237af
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mainwindow.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "vulkanwindow.h"
+#include <QApplication>
+#include <QLabel>
+#include <QPushButton>
+#include <QLCDNumber>
+#include <QCheckBox>
+#include <QGridLayout>
+
+MainWindow::MainWindow(VulkanWindow *vulkanWindow)
+{
+ QWidget *wrapper = QWidget::createWindowContainer(vulkanWindow);
+ wrapper->setFocusPolicy(Qt::StrongFocus);
+ wrapper->setFocus();
+
+ infoLabel = new QLabel;
+ infoLabel->setFrameStyle(QFrame::Box | QFrame::Raised);
+ infoLabel->setAlignment(Qt::AlignCenter);
+ infoLabel->setText(tr("This example demonstrates instanced drawing\nof a mesh loaded from a file.\n"
+ "Uses a Phong material with a single light.\n"
+ "Also demonstrates dynamic uniform buffers\nand a bit of threading with QtConcurrent.\n"
+ "Uses 4x MSAA when available.\n"
+ "Comes with an FPS camera.\n"
+ "Hit [Shift+]WASD to walk and strafe.\nPress and move mouse to look around.\n"
+ "Click Add New to increase the number of instances."));
+
+ meshSwitch = new QCheckBox(tr("&Use Qt logo"));
+ meshSwitch->setFocusPolicy(Qt::NoFocus); // do not interfere with vulkanWindow's keyboard input
+
+ counterLcd = new QLCDNumber(5);
+ counterLcd->setSegmentStyle(QLCDNumber::Filled);
+ counterLcd->display(m_count);
+
+ newButton = new QPushButton(tr("&Add new"));
+ newButton->setFocusPolicy(Qt::NoFocus);
+ quitButton = new QPushButton(tr("&Quit"));
+ quitButton->setFocusPolicy(Qt::NoFocus);
+ pauseButton = new QPushButton(tr("&Pause"));
+ pauseButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(quitButton, &QPushButton::clicked, qApp, &QCoreApplication::quit);
+ connect(newButton, &QPushButton::clicked, vulkanWindow, [=] {
+ vulkanWindow->addNew();
+ m_count = vulkanWindow->instanceCount();
+ counterLcd->display(m_count);
+ });
+ connect(pauseButton, &QPushButton::clicked, vulkanWindow, &VulkanWindow::togglePaused);
+ connect(meshSwitch, &QCheckBox::clicked, vulkanWindow, &VulkanWindow::meshSwitched);
+
+ QGridLayout *layout = new QGridLayout;
+ layout->addWidget(infoLabel, 0, 2);
+ layout->addWidget(meshSwitch, 1, 2);
+ layout->addWidget(createLabel(tr("INSTANCES")), 2, 2);
+ layout->addWidget(counterLcd, 3, 2);
+ layout->addWidget(newButton, 4, 2);
+ layout->addWidget(pauseButton, 5, 2);
+ layout->addWidget(quitButton, 6, 2);
+ layout->addWidget(wrapper, 0, 0, 7, 2);
+ setLayout(layout);
+}
+
+QLabel *MainWindow::createLabel(const QString &text)
+{
+ QLabel *lbl = new QLabel(text);
+ lbl->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
+ return lbl;
+}
diff --git a/examples/widgets/dialogs/configdialog/configdialog.h b/examples/vulkan/hellovulkancubes/mainwindow.h
index c2edd204e6..4109709959 100644
--- a/examples/widgets/dialogs/configdialog/configdialog.h
+++ b/examples/vulkan/hellovulkancubes/mainwindow.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,32 +48,36 @@
**
****************************************************************************/
-#ifndef CONFIGDIALOG_H
-#define CONFIGDIALOG_H
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
-#include <QDialog>
+#include <QWidget>
QT_BEGIN_NAMESPACE
-class QListWidget;
-class QListWidgetItem;
-class QStackedWidget;
+class QLCDNumber;
+class QLabel;
+class QPushButton;
+class QCheckBox;
QT_END_NAMESPACE
-class ConfigDialog : public QDialog
-{
- Q_OBJECT
+class VulkanWindow;
+class MainWindow : public QWidget
+{
public:
- ConfigDialog();
-
-public slots:
- void changePage(QListWidgetItem *current, QListWidgetItem *previous);
+ MainWindow(VulkanWindow *vulkanWindow);
private:
- void createIcons();
+ QLabel *createLabel(const QString &text);
+
+ QLabel *infoLabel;
+ QCheckBox *meshSwitch;
+ QLCDNumber *counterLcd;
+ QPushButton *newButton;
+ QPushButton *quitButton;
+ QPushButton *pauseButton;
- QListWidget *contentsWidget;
- QStackedWidget *pagesWidget;
+ int m_count = 128;
};
#endif
diff --git a/examples/vulkan/hellovulkancubes/mesh.cpp b/examples/vulkan/hellovulkancubes/mesh.cpp
new file mode 100644
index 0000000000..fcc45bfd57
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mesh.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "mesh.h"
+#include <QtConcurrentRun>
+#include <QFile>
+
+void Mesh::load(const QString &fn)
+{
+ reset();
+ m_maybeRunning = true;
+ m_future = QtConcurrent::run([fn]() {
+ MeshData md;
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return md;
+ }
+ QByteArray buf = f.readAll();
+ const char *p = buf.constData();
+ quint32 format;
+ memcpy(&format, p, 4);
+ if (format != 1) {
+ qWarning("Invalid format in %s", qPrintable(fn));
+ return md;
+ }
+ int ofs = 4;
+ memcpy(&md.vertexCount, p + ofs, 4);
+ ofs += 4;
+ memcpy(md.aabb, p + ofs, 6 * 4);
+ ofs += 6 * 4;
+ const int byteCount = md.vertexCount * 8 * 4;
+ md.geom.resize(byteCount);
+ memcpy(md.geom.data(), p + ofs, byteCount);
+ return md;
+ });
+}
+
+MeshData *Mesh::data()
+{
+ if (m_maybeRunning && !m_data.isValid())
+ m_data = m_future.result();
+
+ return &m_data;
+}
+
+void Mesh::reset()
+{
+ *data() = MeshData();
+ m_maybeRunning = false;
+}
diff --git a/examples/widgets/dialogs/configdialog/pages.h b/examples/vulkan/hellovulkancubes/mesh.h
index beb7f86ae0..cb6ee9c830 100644
--- a/examples/widgets/dialogs/configdialog/pages.h
+++ b/examples/vulkan/hellovulkancubes/mesh.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,27 +48,32 @@
**
****************************************************************************/
-#ifndef PAGES_H
-#define PAGES_H
+#ifndef MESH_H
+#define MESH_H
-#include <QWidget>
+#include <QString>
+#include <QFuture>
-class ConfigurationPage : public QWidget
+struct MeshData
{
-public:
- ConfigurationPage(QWidget *parent = 0);
+ bool isValid() const { return vertexCount > 0; }
+ int vertexCount = 0;
+ float aabb[6];
+ QByteArray geom; // x, y, z, u, v, nx, ny, nz
};
-class QueryPage : public QWidget
+class Mesh
{
public:
- QueryPage(QWidget *parent = 0);
-};
+ void load(const QString &fn);
+ MeshData *data();
+ bool isValid() { return data()->isValid(); }
+ void reset();
-class UpdatePage : public QWidget
-{
-public:
- UpdatePage(QWidget *parent = 0);
+private:
+ bool m_maybeRunning = false;
+ QFuture<MeshData> m_future;
+ MeshData m_data;
};
#endif
diff --git a/examples/vulkan/hellovulkancubes/renderer.cpp b/examples/vulkan/hellovulkancubes/renderer.cpp
new file mode 100644
index 0000000000..523511337d
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/renderer.cpp
@@ -0,0 +1,1048 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "renderer.h"
+#include <QVulkanFunctions>
+#include <QtConcurrentRun>
+#include <QTime>
+
+static float quadVert[] = {
+ -1, -1, 0,
+ -1, 1, 0,
+ 1, -1, 0,
+ 1, 1, 0
+};
+
+#define DBG Q_UNLIKELY(m_window->isDebugEnabled())
+
+const int MAX_INSTANCES = 16384;
+const VkDeviceSize PER_INSTANCE_DATA_SIZE = 6 * sizeof(float); // instTranslate, instDiffuseAdjust
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+Renderer::Renderer(VulkanWindow *w, int initialCount)
+ : m_window(w),
+ // Have the light positioned just behind the default camera position, looking forward.
+ m_lightPos(0.0f, 0.0f, 25.0f),
+ m_cam(QVector3D(0.0f, 0.0f, 20.0f)), // starting camera position
+ m_instCount(initialCount)
+{
+ qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
+
+ m_floorModel.translate(0, -5, 0);
+ m_floorModel.rotate(-90, 1, 0, 0);
+ m_floorModel.scale(20, 100, 1);
+
+ m_blockMesh.load(QStringLiteral(":/block.buf"));
+ m_logoMesh.load(QStringLiteral(":/qt_logo.buf"));
+
+ QObject::connect(&m_frameWatcher, &QFutureWatcherBase::finished, [this] {
+ if (m_framePending) {
+ m_framePending = false;
+ m_window->frameReady();
+ m_window->requestUpdate();
+ }
+ });
+}
+
+void Renderer::preInitResources()
+{
+ const QVector<int> sampleCounts = m_window->supportedSampleCounts();
+ if (DBG)
+ qDebug() << "Supported sample counts:" << sampleCounts;
+ if (sampleCounts.contains(4)) {
+ if (DBG)
+ qDebug("Requesting 4x MSAA");
+ m_window->setSampleCount(4);
+ }
+}
+
+void Renderer::initResources()
+{
+ if (DBG)
+ qDebug("Renderer init");
+
+ m_animating = true;
+ m_framePending = false;
+
+ QVulkanInstance *inst = m_window->vulkanInstance();
+ VkDevice dev = m_window->device();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+
+ m_devFuncs = inst->deviceFunctions(dev);
+
+ // Note the std140 packing rules. A vec3 still has an alignment of 16,
+ // while a mat3 is like 3 * vec3.
+ m_itemMaterial.vertUniSize = aligned(2 * 64 + 48, uniAlign); // see color_phong.vert
+ m_itemMaterial.fragUniSize = aligned(6 * 16 + 12 + 2 * 4, uniAlign); // see color_phong.frag
+
+ if (!m_itemMaterial.vs.isValid())
+ m_itemMaterial.vs.load(inst, dev, QStringLiteral(":/color_phong_vert.spv"));
+ if (!m_itemMaterial.fs.isValid())
+ m_itemMaterial.fs.load(inst, dev, QStringLiteral(":/color_phong_frag.spv"));
+
+ if (!m_floorMaterial.vs.isValid())
+ m_floorMaterial.vs.load(inst, dev, QStringLiteral(":/color_vert.spv"));
+ if (!m_floorMaterial.fs.isValid())
+ m_floorMaterial.fs.load(inst, dev, QStringLiteral(":/color_frag.spv"));
+
+ m_pipelinesFuture = QtConcurrent::run(this, &Renderer::createPipelines);
+}
+
+void Renderer::createPipelines()
+{
+ VkDevice dev = m_window->device();
+
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ VkResult err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ createItemPipeline();
+ createFloorPipeline();
+}
+
+void Renderer::createItemPipeline()
+{
+ VkDevice dev = m_window->device();
+
+ // Vertex layout.
+ VkVertexInputBindingDescription vertexBindingDesc[] = {
+ {
+ 0, // binding
+ 8 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ },
+ {
+ 1,
+ 6 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_INSTANCE
+ }
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0 // offset
+ },
+ { // normal
+ 1,
+ 0,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 5 * sizeof(float)
+ },
+ { // instTranslate
+ 2,
+ 1,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0
+ },
+ { // instDiffuseAdjust
+ 3,
+ 1,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 3 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = sizeof(vertexBindingDesc) / sizeof(vertexBindingDesc[0]);
+ vertexInputInfo.pVertexBindingDescriptions = vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = sizeof(vertexAttrDesc) / sizeof(vertexAttrDesc[0]);
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Descriptor set layout.
+ VkDescriptorPoolSize descPoolSizes[] = {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 2 }
+ };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = 1; // a single set is enough due to the dynamic uniform buffer
+ descPoolInfo.poolSizeCount = sizeof(descPoolSizes) / sizeof(descPoolSizes[0]);
+ descPoolInfo.pPoolSizes = descPoolSizes;
+ VkResult err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_itemMaterial.descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBindings[] =
+ {
+ {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ },
+ {
+ 1,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ 1,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ nullptr
+ }
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ sizeof(layoutBindings) / sizeof(layoutBindings[0]),
+ layoutBindings
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_itemMaterial.descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_itemMaterial.descPool,
+ 1,
+ &m_itemMaterial.descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_itemMaterial.descSet);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ // Graphics pipeline.
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_itemMaterial.descSetLayout;
+
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_itemMaterial.pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ m_itemMaterial.vs.data()->shaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ m_itemMaterial.fs.data()->shaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_itemMaterial.pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_itemMaterial.pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+}
+
+void Renderer::createFloorPipeline()
+{
+ VkDevice dev = m_window->device();
+
+ // Vertex layout.
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 3 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0 // offset
+ },
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = sizeof(vertexAttrDesc) / sizeof(vertexAttrDesc[0]);
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Do not bother with uniform buffers and descriptors, all the data fits
+ // into the spec mandated minimum of 128 bytes for push constants.
+ VkPushConstantRange pcr[] = {
+ // mvp
+ {
+ VK_SHADER_STAGE_VERTEX_BIT,
+ 0,
+ 64
+ },
+ // color
+ {
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ 64,
+ 12
+ }
+ };
+
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.pushConstantRangeCount = sizeof(pcr) / sizeof(pcr[0]);
+ pipelineLayoutInfo.pPushConstantRanges = pcr;
+
+ VkResult err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_floorMaterial.pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ m_floorMaterial.vs.data()->shaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ m_floorMaterial.fs.data()->shaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_floorMaterial.pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_floorMaterial.pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+}
+
+void Renderer::initSwapChainResources()
+{
+ m_proj = m_window->clipCorrectionMatrix();
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 1000.0f);
+ markViewProjDirty();
+}
+
+void Renderer::releaseSwapChainResources()
+{
+ // It is important to finish the pending frame right here since this is the
+ // last opportunity to act with all resources intact.
+ m_frameWatcher.waitForFinished();
+ // Cannot count on the finished() signal being emitted before returning
+ // from here.
+ if (m_framePending) {
+ m_framePending = false;
+ m_window->frameReady();
+ }
+}
+
+void Renderer::releaseResources()
+{
+ if (DBG)
+ qDebug("Renderer release");
+
+ m_pipelinesFuture.waitForFinished();
+
+ VkDevice dev = m_window->device();
+
+ if (m_itemMaterial.descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_itemMaterial.descSetLayout, nullptr);
+ m_itemMaterial.descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_itemMaterial.descPool, nullptr);
+ m_itemMaterial.descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_itemMaterial.pipeline, nullptr);
+ m_itemMaterial.pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_itemMaterial.pipelineLayout, nullptr);
+ m_itemMaterial.pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_floorMaterial.pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_floorMaterial.pipeline, nullptr);
+ m_floorMaterial.pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_floorMaterial.pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_floorMaterial.pipelineLayout, nullptr);
+ m_floorMaterial.pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_blockVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_blockVertexBuf, nullptr);
+ m_blockVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_logoVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_logoVertexBuf, nullptr);
+ m_logoVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_floorVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_floorVertexBuf, nullptr);
+ m_floorVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_uniBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_uniBuf, nullptr);
+ m_uniBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+
+ if (m_instBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_instBuf, nullptr);
+ m_instBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_instBufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_instBufMem, nullptr);
+ m_instBufMem = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.vs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_itemMaterial.vs.data()->shaderModule, nullptr);
+ m_itemMaterial.vs.reset();
+ }
+ if (m_itemMaterial.fs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_itemMaterial.fs.data()->shaderModule, nullptr);
+ m_itemMaterial.fs.reset();
+ }
+
+ if (m_floorMaterial.vs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_floorMaterial.vs.data()->shaderModule, nullptr);
+ m_floorMaterial.vs.reset();
+ }
+ if (m_floorMaterial.fs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_floorMaterial.fs.data()->shaderModule, nullptr);
+ m_floorMaterial.fs.reset();
+ }
+}
+
+void Renderer::ensureBuffers()
+{
+ if (m_blockVertexBuf)
+ return;
+
+ VkDevice dev = m_window->device();
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+
+ // Vertex buffer for the block.
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ const int blockMeshByteCount = m_blockMesh.data()->vertexCount * 8 * sizeof(float);
+ bufInfo.size = blockMeshByteCount;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_blockVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements blockVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_blockVertexBuf, &blockVertMemReq);
+
+ // Vertex buffer for the logo.
+ const int logoMeshByteCount = m_logoMesh.data()->vertexCount * 8 * sizeof(float);
+ bufInfo.size = logoMeshByteCount;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_logoVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements logoVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_logoVertexBuf, &logoVertMemReq);
+
+ // Vertex buffer for the floor.
+ bufInfo.size = sizeof(quadVert);
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_floorVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements floorVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_floorVertexBuf, &floorVertMemReq);
+
+ // Uniform buffer. Instead of using multiple descriptor sets, we take a
+ // different approach: have a single dynamic uniform buffer and specify the
+ // active-frame-specific offset at the time of binding the descriptor set.
+ bufInfo.size = (m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize) * concurrentFrameCount;
+ bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_uniBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create uniform buffer: %d", err);
+
+ VkMemoryRequirements uniMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_uniBuf, &uniMemReq);
+
+ // Allocate memory for everything at once.
+ VkDeviceSize logoVertStartOffset = aligned(0 + blockVertMemReq.size, logoVertMemReq.alignment);
+ VkDeviceSize floorVertStartOffset = aligned(logoVertStartOffset + logoVertMemReq.size, floorVertMemReq.alignment);
+ m_itemMaterial.uniMemStartOffset = aligned(floorVertStartOffset + floorVertMemReq.size, uniMemReq.alignment);
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ m_itemMaterial.uniMemStartOffset + uniMemReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_blockVertexBuf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_logoVertexBuf, m_bufMem, logoVertStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_floorVertexBuf, m_bufMem, floorVertStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_uniBuf, m_bufMem, m_itemMaterial.uniMemStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind uniform buffer memory: %d", err);
+
+ // Copy vertex data.
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, m_itemMaterial.uniMemStartOffset, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, m_blockMesh.data()->geom.constData(), blockMeshByteCount);
+ memcpy(p + logoVertStartOffset, m_logoMesh.data()->geom.constData(), logoMeshByteCount);
+ memcpy(p + floorVertStartOffset, quadVert, sizeof(quadVert));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Write descriptors for the uniform buffers in the vertex and fragment shaders.
+ VkDescriptorBufferInfo vertUni = { m_uniBuf, 0, m_itemMaterial.vertUniSize };
+ VkDescriptorBufferInfo fragUni = { m_uniBuf, m_itemMaterial.vertUniSize, m_itemMaterial.fragUniSize };
+
+ VkWriteDescriptorSet descWrite[2];
+ memset(descWrite, 0, sizeof(descWrite));
+ descWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[0].dstSet = m_itemMaterial.descSet;
+ descWrite[0].dstBinding = 0;
+ descWrite[0].descriptorCount = 1;
+ descWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ descWrite[0].pBufferInfo = &vertUni;
+
+ descWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[1].dstSet = m_itemMaterial.descSet;
+ descWrite[1].dstBinding = 1;
+ descWrite[1].descriptorCount = 1;
+ descWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ descWrite[1].pBufferInfo = &fragUni;
+
+ m_devFuncs->vkUpdateDescriptorSets(dev, 2, descWrite, 0, nullptr);
+}
+
+void Renderer::ensureInstanceBuffer()
+{
+ if (m_instCount == m_preparedInstCount && m_instBuf)
+ return;
+
+ Q_ASSERT(m_instCount <= MAX_INSTANCES);
+
+ VkDevice dev = m_window->device();
+
+ // allocate only once, for the maximum instance count
+ if (!m_instBuf) {
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufInfo.size = MAX_INSTANCES * PER_INSTANCE_DATA_SIZE;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+ // Keep a copy of the data since we may lose all graphics resources on
+ // unexpose, and reinitializing to new random positions afterwards
+ // would not be nice.
+ m_instData.resize(bufInfo.size);
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_instBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create instance buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_instBuf, &memReq);
+ if (DBG)
+ qDebug("Allocating %u bytes for instance data", uint32_t(memReq.size));
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_instBufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_instBuf, m_instBufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind instance buffer memory: %d", err);
+ }
+
+ if (m_instCount != m_preparedInstCount) {
+ if (DBG)
+ qDebug("Preparing instances %d..%d", m_preparedInstCount, m_instCount - 1);
+ char *p = m_instData.data();
+ p += m_preparedInstCount * PER_INSTANCE_DATA_SIZE;
+ auto gen = [](float a, float b) { return float((qrand() % int(b - a + 1)) + a); };
+ for (int i = m_preparedInstCount; i < m_instCount; ++i) {
+ // Apply a random translation to each instance of the mesh.
+ float t[] = { gen(-5, 5), gen(-4, 6), gen(-30, 5) };
+ memcpy(p, t, 12);
+ // Apply a random adjustment to the diffuse color for each instance. (default is 0.7)
+ float d[] = { gen(-6, 3) / 10.0f, gen(-6, 3) / 10.0f, gen(-6, 3) / 10.0f };
+ memcpy(p + 12, d, 12);
+ p += PER_INSTANCE_DATA_SIZE;
+ }
+ m_preparedInstCount = m_instCount;
+ }
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_instBufMem, 0, m_instCount * PER_INSTANCE_DATA_SIZE, 0,
+ reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, m_instData.constData(), m_instData.size());
+ m_devFuncs->vkUnmapMemory(dev, m_instBufMem);
+}
+
+void Renderer::getMatrices(QMatrix4x4 *vp, QMatrix4x4 *model, QMatrix3x3 *modelNormal, QVector3D *eyePos)
+{
+ model->setToIdentity();
+ if (m_useLogo)
+ model->rotate(90, 1, 0, 0);
+ model->rotate(m_rotation, 1, 1, 0);
+
+ *modelNormal = model->normalMatrix();
+
+ QMatrix4x4 view = m_cam.viewMatrix();
+ *vp = m_proj * view;
+
+ *eyePos = view.inverted().column(3).toVector3D();
+}
+
+void Renderer::writeFragUni(quint8 *p, const QVector3D &eyePos)
+{
+ float ECCameraPosition[] = { eyePos.x(), eyePos.y(), eyePos.z() };
+ memcpy(p, ECCameraPosition, 12);
+ p += 16;
+
+ // Material
+ float ka[] = { 0.05f, 0.05f, 0.05f };
+ memcpy(p, ka, 12);
+ p += 16;
+
+ float kd[] = { 0.7f, 0.7f, 0.7f };
+ memcpy(p, kd, 12);
+ p += 16;
+
+ float ks[] = { 0.66f, 0.66f, 0.66f };
+ memcpy(p, ks, 12);
+ p += 16;
+
+ // Light parameters
+ float ECLightPosition[] = { m_lightPos.x(), m_lightPos.y(), m_lightPos.z() };
+ memcpy(p, ECLightPosition, 12);
+ p += 16;
+
+ float att[] = { 1, 0, 0 };
+ memcpy(p, att, 12);
+ p += 16;
+
+ float color[] = { 1.0f, 1.0f, 1.0f };
+ memcpy(p, color, 12);
+ p += 12; // next we have two floats which have an alignment of 4, hence 12 only
+
+ float intensity = 0.8f;
+ memcpy(p, &intensity, 4);
+ p += 4;
+
+ float specularExp = 150.0f;
+ memcpy(p, &specularExp, 4);
+ p += 4;
+}
+
+void Renderer::startNextFrame()
+{
+ // For demonstration purposes offload the command buffer generation onto a
+ // worker thread and continue with the frame submission only when it has
+ // finished.
+ Q_ASSERT(!m_framePending);
+ m_framePending = true;
+ QFuture<void> future = QtConcurrent::run(this, &Renderer::buildFrame);
+ m_frameWatcher.setFuture(future);
+}
+
+void Renderer::buildFrame()
+{
+ QMutexLocker locker(&m_guiMutex);
+
+ ensureBuffers();
+ ensureInstanceBuffer();
+ m_pipelinesFuture.waitForFinished();
+
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ VkClearColorValue clearColor = { 0.67f, 0.84f, 0.9f, 1.0f };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[3];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearValues[2].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = m_window->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ VkViewport viewport = {
+ 0, 0,
+ float(sz.width()), float(sz.height()),
+ 0, 1
+ };
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor = {
+ { 0, 0 },
+ { uint32_t(sz.width()), uint32_t(sz.height()) }
+ };
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ buildDrawCallsForFloor();
+ buildDrawCallsForItems();
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+}
+
+void Renderer::buildDrawCallsForItems()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_itemMaterial.pipeline);
+
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, m_useLogo ? &m_logoVertexBuf : &m_blockVertexBuf, &vbOffset);
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 1, 1, &m_instBuf, &vbOffset);
+
+ // Now provide offsets so that the two dynamic buffers point to the
+ // beginning of the vertex and fragment uniform data for the current frame.
+ uint32_t frameUniOffset = m_window->currentFrame() * (m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize);
+ uint32_t frameUniOffsets[] = { frameUniOffset, frameUniOffset };
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_itemMaterial.pipelineLayout, 0, 1,
+ &m_itemMaterial.descSet, 2, frameUniOffsets);
+
+ if (m_animating)
+ m_rotation += 0.5;
+
+ if (m_animating || m_vpDirty) {
+ if (m_vpDirty)
+ --m_vpDirty;
+ QMatrix4x4 vp, model;
+ QMatrix3x3 modelNormal;
+ QVector3D eyePos;
+ getMatrices(&vp, &model, &modelNormal, &eyePos);
+
+ // Map the uniform data for the current frame, ignore the geometry data at
+ // the beginning and the uniforms for other frames.
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem,
+ m_itemMaterial.uniMemStartOffset + frameUniOffset,
+ m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize,
+ 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+
+ // Vertex shader uniforms
+ memcpy(p, vp.constData(), 64);
+ memcpy(p + 64, model.constData(), 64);
+ const float *mnp = modelNormal.constData();
+ memcpy(p + 128, mnp, 12);
+ memcpy(p + 128 + 16, mnp + 3, 12);
+ memcpy(p + 128 + 32, mnp + 6, 12);
+
+ // Fragment shader uniforms
+ p += m_itemMaterial.vertUniSize;
+ writeFragUni(p, eyePos);
+
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+ }
+
+ m_devFuncs->vkCmdDraw(cb, (m_useLogo ? m_logoMesh.data() : m_blockMesh.data())->vertexCount, m_instCount, 0, 0);
+}
+
+void Renderer::buildDrawCallsForFloor()
+{
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_floorMaterial.pipeline);
+
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_floorVertexBuf, &vbOffset);
+
+ QMatrix4x4 mvp = m_proj * m_cam.viewMatrix() * m_floorModel;
+ m_devFuncs->vkCmdPushConstants(cb, m_floorMaterial.pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, 64, mvp.constData());
+ float color[] = { 0.67f, 1.0f, 0.2f };
+ m_devFuncs->vkCmdPushConstants(cb, m_floorMaterial.pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 64, 12, color);
+
+ m_devFuncs->vkCmdDraw(cb, 4, 1, 0, 0);
+}
+
+void Renderer::addNew()
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_instCount = qMin(m_instCount + 16, MAX_INSTANCES);
+}
+
+void Renderer::yaw(float degrees)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.yaw(degrees);
+ markViewProjDirty();
+}
+
+void Renderer::pitch(float degrees)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.pitch(degrees);
+ markViewProjDirty();
+}
+
+void Renderer::walk(float amount)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.walk(amount);
+ markViewProjDirty();
+}
+
+void Renderer::strafe(float amount)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.strafe(amount);
+ markViewProjDirty();
+}
+
+void Renderer::setUseLogo(bool b)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_useLogo = b;
+ if (!m_animating)
+ m_window->requestUpdate();
+}
diff --git a/examples/vulkan/hellovulkancubes/renderer.h b/examples/vulkan/hellovulkancubes/renderer.h
new file mode 100644
index 0000000000..60bb48377e
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/renderer.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include "vulkanwindow.h"
+#include "mesh.h"
+#include "shader.h"
+#include "camera.h"
+#include <QFutureWatcher>
+#include <QMutex>
+
+class Renderer : public QVulkanWindowRenderer
+{
+public:
+ Renderer(VulkanWindow *w, int initialCount);
+
+ void preInitResources() override;
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+ bool animating() const { return m_animating; }
+ void setAnimating(bool a) { m_animating = a; }
+
+ int instanceCount() const { return m_instCount; }
+ void addNew();
+
+ void yaw(float degrees);
+ void pitch(float degrees);
+ void walk(float amount);
+ void strafe(float amount);
+
+ void setUseLogo(bool b);
+
+private:
+ void createPipelines();
+ void createItemPipeline();
+ void createFloorPipeline();
+ void ensureBuffers();
+ void ensureInstanceBuffer();
+ void getMatrices(QMatrix4x4 *mvp, QMatrix4x4 *model, QMatrix3x3 *modelNormal, QVector3D *eyePos);
+ void writeFragUni(quint8 *p, const QVector3D &eyePos);
+ void buildFrame();
+ void buildDrawCallsForItems();
+ void buildDrawCallsForFloor();
+
+ void markViewProjDirty() { m_vpDirty = m_window->concurrentFrameCount(); }
+
+ VulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ bool m_useLogo = false;
+ Mesh m_blockMesh;
+ Mesh m_logoMesh;
+ VkBuffer m_blockVertexBuf = VK_NULL_HANDLE;
+ VkBuffer m_logoVertexBuf = VK_NULL_HANDLE;
+ struct {
+ VkDeviceSize vertUniSize;
+ VkDeviceSize fragUniSize;
+ VkDeviceSize uniMemStartOffset;
+ Shader vs;
+ Shader fs;
+ VkDescriptorPool descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet descSet;
+ VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ } m_itemMaterial;
+
+ VkBuffer m_floorVertexBuf = VK_NULL_HANDLE;
+ struct {
+ Shader vs;
+ Shader fs;
+ VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ } m_floorMaterial;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_uniBuf = VK_NULL_HANDLE;
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ QFuture<void> m_pipelinesFuture;
+
+ QVector3D m_lightPos;
+ Camera m_cam;
+
+ QMatrix4x4 m_proj;
+ int m_vpDirty = 0;
+ QMatrix4x4 m_floorModel;
+
+ bool m_animating;
+ float m_rotation = 0.0f;
+
+ int m_instCount;
+ int m_preparedInstCount = 0;
+ QByteArray m_instData;
+ VkBuffer m_instBuf = VK_NULL_HANDLE;
+ VkDeviceMemory m_instBufMem = VK_NULL_HANDLE;
+
+ QFutureWatcher<void> m_frameWatcher;
+ bool m_framePending;
+
+ QMutex m_guiMutex;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/shader.cpp b/examples/vulkan/hellovulkancubes/shader.cpp
new file mode 100644
index 0000000000..e1c01c6842
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/shader.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "shader.h"
+#include <QtConcurrentRun>
+#include <QFile>
+#include <QVulkanDeviceFunctions>
+
+void Shader::load(QVulkanInstance *inst, VkDevice dev, const QString &fn)
+{
+ reset();
+ m_maybeRunning = true;
+ m_future = QtConcurrent::run([inst, dev, fn]() {
+ ShaderData sd;
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return sd;
+ }
+ QByteArray blob = f.readAll();
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkResult err = inst->deviceFunctions(dev)->vkCreateShaderModule(dev, &shaderInfo, nullptr, &sd.shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return sd;
+ }
+ return sd;
+ });
+}
+
+ShaderData *Shader::data()
+{
+ if (m_maybeRunning && !m_data.isValid())
+ m_data = m_future.result();
+
+ return &m_data;
+}
+
+void Shader::reset()
+{
+ *data() = ShaderData();
+ m_maybeRunning = false;
+}
diff --git a/examples/widgets/effects/lighting/main.cpp b/examples/vulkan/hellovulkancubes/shader.h
index 22e55c0985..265868d2b0 100644
--- a/examples/widgets/effects/lighting/main.cpp
+++ b/examples/vulkan/hellovulkancubes/shader.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,18 +48,30 @@
**
****************************************************************************/
-#include "lighting.h"
-#include <QApplication>
+#ifndef SHADER_H
+#define SHADER_H
-int main(int argc, char **argv)
+#include <QVulkanInstance>
+#include <QFuture>
+
+struct ShaderData
{
- QApplication app(argc, argv);
+ bool isValid() const { return shaderModule != VK_NULL_HANDLE; }
+ VkShaderModule shaderModule = VK_NULL_HANDLE;
+};
- Lighting lighting;
- lighting.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Lighting and Shadows"));
+class Shader
+{
+public:
+ void load(QVulkanInstance *inst, VkDevice dev, const QString &fn);
+ ShaderData *data();
+ bool isValid() { return data()->isValid(); }
+ void reset();
- lighting.resize(640, 480);
- lighting.show();
+private:
+ bool m_maybeRunning = false;
+ QFuture<ShaderData> m_future;
+ ShaderData m_data;
+};
- return app.exec();
-}
+#endif
diff --git a/examples/vulkan/hellovulkancubes/vulkanwindow.cpp b/examples/vulkan/hellovulkancubes/vulkanwindow.cpp
new file mode 100644
index 0000000000..9a4eaf1901
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/vulkanwindow.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "vulkanwindow.h"
+#include "renderer.h"
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+VulkanWindow::VulkanWindow(bool dbg)
+ : m_debug(dbg)
+{
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ m_renderer = new Renderer(this, 128);
+ return m_renderer;
+}
+
+void VulkanWindow::addNew()
+{
+ m_renderer->addNew();
+}
+
+void VulkanWindow::togglePaused()
+{
+ m_renderer->setAnimating(!m_renderer->animating());
+}
+
+void VulkanWindow::meshSwitched(bool enable)
+{
+ m_renderer->setUseLogo(enable);
+}
+
+void VulkanWindow::mousePressEvent(QMouseEvent *e)
+{
+ m_pressed = true;
+ m_lastPos = e->pos();
+}
+
+void VulkanWindow::mouseReleaseEvent(QMouseEvent *)
+{
+ m_pressed = false;
+}
+
+void VulkanWindow::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!m_pressed)
+ return;
+
+ int dx = e->pos().x() - m_lastPos.x();
+ int dy = e->pos().y() - m_lastPos.y();
+
+ if (dy)
+ m_renderer->pitch(dy / 10.0f);
+
+ if (dx)
+ m_renderer->yaw(dx / 10.0f);
+
+ m_lastPos = e->pos();
+}
+
+void VulkanWindow::keyPressEvent(QKeyEvent *e)
+{
+ const float amount = e->modifiers().testFlag(Qt::ShiftModifier) ? 1.0f : 0.1f;
+ switch (e->key()) {
+ case Qt::Key_W:
+ m_renderer->walk(amount);
+ break;
+ case Qt::Key_S:
+ m_renderer->walk(-amount);
+ break;
+ case Qt::Key_A:
+ m_renderer->strafe(-amount);
+ break;
+ case Qt::Key_D:
+ m_renderer->strafe(amount);
+ break;
+ default:
+ break;
+ }
+}
+
+int VulkanWindow::instanceCount() const
+{
+ return m_renderer->instanceCount();
+}
diff --git a/examples/vulkan/hellovulkancubes/vulkanwindow.h b/examples/vulkan/hellovulkancubes/vulkanwindow.h
new file mode 100644
index 0000000000..d085c0bde7
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/vulkanwindow.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#ifndef VULKANWINDOW_H
+#define VULKANWINDOW_H
+
+#include <QVulkanWindow>
+
+class Renderer;
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ VulkanWindow(bool dbg);
+
+ QVulkanWindowRenderer *createRenderer() override;
+
+ bool isDebugEnabled() const { return m_debug; }
+ int instanceCount() const;
+
+public slots:
+ void addNew();
+ void togglePaused();
+ void meshSwitched(bool enable);
+
+private:
+ void mousePressEvent(QMouseEvent *) override;
+ void mouseReleaseEvent(QMouseEvent *) override;
+ void mouseMoveEvent(QMouseEvent *) override;
+ void keyPressEvent(QKeyEvent *) override;
+
+ bool m_debug;
+ Renderer *m_renderer;
+ bool m_pressed = false;
+ QPoint m_lastPos;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp b/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
new file mode 100644
index 0000000000..543eb7884a
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
@@ -0,0 +1,829 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "hellovulkantexture.h"
+#include <QVulkanFunctions>
+#include <QCoreApplication>
+#include <QFile>
+
+// Use a triangle strip to get a quad.
+//
+// Note that the vertex data and the projection matrix assume OpenGL. With
+// Vulkan Y is negated in clip space and the near/far plane is at 0/1 instead
+// of -1/1. These will be corrected for by an extra transformation when
+// calculating the modelview-projection matrix.
+static float vertexData[] = {
+ // x, y, z, u, v
+ -1, -1, 0, 0, 1,
+ -1, 1, 0, 0, 0,
+ 1, -1, 0, 1, 1,
+ 1, 1, 0, 1, 0
+};
+
+static const int UNIFORM_DATA_SIZE = 16 * sizeof(float);
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(QVulkanWindow *w)
+ : m_window(w)
+{
+}
+
+VkShaderModule VulkanRenderer::createShader(const QString &name)
+{
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to read shader %s", qPrintable(name));
+ return VK_NULL_HANDLE;
+ }
+ QByteArray blob = file.readAll();
+ file.close();
+
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkShaderModule shaderModule;
+ VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return VK_NULL_HANDLE;
+ }
+
+ return shaderModule;
+}
+
+bool VulkanRenderer::createTexture(const QString &name)
+{
+ QImage img(name);
+ if (img.isNull()) {
+ qWarning("Failed to load image %s", qPrintable(name));
+ return false;
+ }
+
+ // Convert to byte ordered RGBA8. Use premultiplied alpha, see pColorBlendState in the pipeline.
+ img = img.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+
+ QVulkanFunctions *f = m_window->vulkanInstance()->functions();
+ VkDevice dev = m_window->device();
+
+ const bool srgb = QCoreApplication::arguments().contains(QStringLiteral("--srgb"));
+ if (srgb)
+ qDebug("sRGB swapchain was requested, making texture sRGB too");
+
+ m_texFormat = srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
+
+ // Now we can either map and copy the image data directly, or have to go
+ // through a staging buffer to copy and convert into the internal optimal
+ // tiling format.
+ VkFormatProperties props;
+ f->vkGetPhysicalDeviceFormatProperties(m_window->physicalDevice(), m_texFormat, &props);
+ const bool canSampleLinear = (props.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
+ const bool canSampleOptimal = (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
+ if (!canSampleLinear && !canSampleOptimal) {
+ qWarning("Neither linear nor optimal image sampling is supported for RGBA8");
+ return false;
+ }
+
+ static bool alwaysStage = qEnvironmentVariableIntValue("QT_VK_FORCE_STAGE_TEX");
+
+ if (canSampleLinear && !alwaysStage) {
+ if (!createTextureImage(img.size(), &m_texImage, &m_texMem,
+ VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_SAMPLED_BIT,
+ m_window->hostVisibleMemoryIndex()))
+ return false;
+
+ if (!writeLinearImage(img, m_texImage, m_texMem))
+ return false;
+
+ m_texLayoutPending = true;
+ } else {
+ if (!createTextureImage(img.size(), &m_texStaging, &m_texStagingMem,
+ VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+ m_window->hostVisibleMemoryIndex()))
+ return false;
+
+ if (!createTextureImage(img.size(), &m_texImage, &m_texMem,
+ VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ m_window->deviceLocalMemoryIndex()))
+ return false;
+
+ if (!writeLinearImage(img, m_texStaging, m_texStagingMem))
+ return false;
+
+ m_texStagingPending = true;
+ }
+
+ VkImageViewCreateInfo viewInfo;
+ memset(&viewInfo, 0, sizeof(viewInfo));
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = m_texImage;
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = m_texFormat;
+ viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ viewInfo.subresourceRange.levelCount = viewInfo.subresourceRange.layerCount = 1;
+
+ VkResult err = m_devFuncs->vkCreateImageView(dev, &viewInfo, nullptr, &m_texView);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create image view for texture: %d", err);
+ return false;
+ }
+
+ m_texSize = img.size();
+
+ return true;
+}
+
+bool VulkanRenderer::createTextureImage(const QSize &size, VkImage *image, VkDeviceMemory *mem,
+ VkImageTiling tiling, VkImageUsageFlags usage, uint32_t memIndex)
+{
+ VkDevice dev = m_window->device();
+
+ VkImageCreateInfo imageInfo;
+ memset(&imageInfo, 0, sizeof(imageInfo));
+ imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageInfo.format = m_texFormat;
+ imageInfo.extent.width = size.width();
+ imageInfo.extent.height = size.height();
+ imageInfo.extent.depth = 1;
+ imageInfo.mipLevels = 1;
+ imageInfo.arrayLayers = 1;
+ imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ imageInfo.tiling = tiling;
+ imageInfo.usage = usage;
+ imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+
+ VkResult err = m_devFuncs->vkCreateImage(dev, &imageInfo, nullptr, image);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create linear image for texture: %d", err);
+ return false;
+ }
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetImageMemoryRequirements(dev, *image, &memReq);
+
+ VkMemoryAllocateInfo allocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ memIndex
+ };
+ qDebug("allocating %u bytes for texture image", uint32_t(memReq.size));
+
+ err = m_devFuncs->vkAllocateMemory(dev, &allocInfo, nullptr, mem);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to allocate memory for linear image: %d", err);
+ return false;
+ }
+
+ err = m_devFuncs->vkBindImageMemory(dev, *image, *mem, 0);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to bind linear image memory: %d", err);
+ return false;
+ }
+
+ return true;
+}
+
+bool VulkanRenderer::writeLinearImage(const QImage &img, VkImage image, VkDeviceMemory memory)
+{
+ VkDevice dev = m_window->device();
+
+ VkImageSubresource subres = {
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ 0, // mip level
+ 0
+ };
+ VkSubresourceLayout layout;
+ m_devFuncs->vkGetImageSubresourceLayout(dev, image, &subres, &layout);
+
+ uchar *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, memory, layout.offset, layout.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to map memory for linear image: %d", err);
+ return false;
+ }
+
+ for (int y = 0; y < img.height(); ++y) {
+ const uchar *line = img.constScanLine(y);
+ memcpy(p, line, img.width() * 4);
+ p += layout.rowPitch;
+ }
+
+ m_devFuncs->vkUnmapMemory(dev, memory);
+ return true;
+}
+
+void VulkanRenderer::ensureTexture()
+{
+ if (!m_texLayoutPending && !m_texStagingPending)
+ return;
+
+ Q_ASSERT(m_texLayoutPending != m_texStagingPending);
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ VkImageMemoryBarrier barrier;
+ memset(&barrier, 0, sizeof(barrier));
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.levelCount = barrier.subresourceRange.layerCount = 1;
+
+ if (m_texLayoutPending) {
+ m_texLayoutPending = false;
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ barrier.srcAccessMask = 0; // VK_ACCESS_HOST_WRITE_BIT ### no, keep validation layer happy (??)
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ barrier.image = m_texImage;
+
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+ } else {
+ m_texStagingPending = false;
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ barrier.image = m_texStaging;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.image = m_texImage;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+
+ VkImageCopy copyInfo;
+ memset(&copyInfo, 0, sizeof(copyInfo));
+ copyInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyInfo.srcSubresource.layerCount = 1;
+ copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyInfo.dstSubresource.layerCount = 1;
+ copyInfo.extent.width = m_texSize.width();
+ copyInfo.extent.height = m_texSize.height();
+ copyInfo.extent.depth = 1;
+ m_devFuncs->vkCmdCopyImage(cb, m_texStaging, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ m_texImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copyInfo);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ barrier.image = m_texImage;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+ }
+}
+
+void VulkanRenderer::initResources()
+{
+ qDebug("initResources");
+
+ VkDevice dev = m_window->device();
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev);
+
+ // The setup is similar to hellovulkantriangle. The difference is the
+ // presence of a second vertex attribute (texcoord), a sampler, and that we
+ // need blending.
+
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+ qDebug("uniform buffer offset alignment is %u", (uint) uniAlign);
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ // Our internal layout is vertex, uniform, uniform, ... with each uniform buffer start offset aligned to uniAlign.
+ const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign);
+ const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign);
+ bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_buf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_buf, &memReq);
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_buf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind buffer memory: %d", err);
+
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, memReq.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, vertexData, sizeof(vertexData));
+ QMatrix4x4 ident;
+ memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
+ memcpy(p + offset, ident.constData(), 16 * sizeof(float));
+ m_uniformBufInfo[i].buffer = m_buf;
+ m_uniformBufInfo[i].offset = offset;
+ m_uniformBufInfo[i].range = uniformAllocSize;
+ }
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 5 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0
+ },
+ { // texcoord
+ 1,
+ 0,
+ VK_FORMAT_R32G32_SFLOAT,
+ 3 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = 2;
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Sampler.
+ VkSamplerCreateInfo samplerInfo;
+ memset(&samplerInfo, 0, sizeof(samplerInfo));
+ samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ samplerInfo.magFilter = VK_FILTER_NEAREST;
+ samplerInfo.minFilter = VK_FILTER_NEAREST;
+ samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.maxAnisotropy = 1.0f;
+ err = m_devFuncs->vkCreateSampler(dev, &samplerInfo, nullptr, &m_sampler);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create sampler: %d", err);
+
+ // Texture.
+ if (!createTexture(QStringLiteral(":/qt256.png")))
+ qFatal("Failed to create texture");
+
+ // Set up descriptor set and its layout.
+ VkDescriptorPoolSize descPoolSizes[2] = {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uint32_t(concurrentFrameCount) },
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, uint32_t(concurrentFrameCount) }
+ };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = concurrentFrameCount;
+ descPoolInfo.poolSizeCount = 2;
+ descPoolInfo.pPoolSizes = descPoolSizes;
+ err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBinding[2] =
+ {
+ {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ },
+ {
+ 1, // binding
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ nullptr
+ }
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ 2, // bindingCount
+ layoutBinding
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_descPool,
+ 1,
+ &m_descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_descSet[i]);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ VkWriteDescriptorSet descWrite[2];
+ memset(descWrite, 0, sizeof(descWrite));
+ descWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[0].dstSet = m_descSet[i];
+ descWrite[0].dstBinding = 0;
+ descWrite[0].descriptorCount = 1;
+ descWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descWrite[0].pBufferInfo = &m_uniformBufInfo[i];
+
+ VkDescriptorImageInfo descImageInfo = {
+ m_sampler,
+ m_texView,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+ };
+
+ descWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[1].dstSet = m_descSet[i];
+ descWrite[1].dstBinding = 1;
+ descWrite[1].descriptorCount = 1;
+ descWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ descWrite[1].pImageInfo = &descImageInfo;
+
+ m_devFuncs->vkUpdateDescriptorSets(dev, 2, descWrite, 0, nullptr);
+ }
+
+ // Pipeline cache
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ // Pipeline layout
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_descSetLayout;
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ // Shaders
+ VkShaderModule vertShaderModule = createShader(QStringLiteral(":/texture_vert.spv"));
+ VkShaderModule fragShaderModule = createShader(QStringLiteral(":/texture_frag.spv"));
+
+ // Graphics pipeline
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ vertShaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ fragShaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ // The viewport and scissor will be set dynamically via vkCmdSetViewport/Scissor.
+ // This way the pipeline does not need to be touched when resizing the window.
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ // assume pre-multiplied alpha, blend, write out all of rgba
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ att.blendEnable = VK_TRUE;
+ att.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
+ att.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ att.colorBlendOp = VK_BLEND_OP_ADD;
+ att.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ att.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ att.alphaBlendOp = VK_BLEND_OP_ADD;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+
+ if (vertShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, vertShaderModule, nullptr);
+ if (fragShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr);
+}
+
+void VulkanRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+
+ // Projection matrix
+ m_proj = m_window->clipCorrectionMatrix(); // adjust for Vulkan-OpenGL clip space differences
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void VulkanRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void VulkanRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+
+ VkDevice dev = m_window->device();
+
+ if (m_sampler) {
+ m_devFuncs->vkDestroySampler(dev, m_sampler, nullptr);
+ m_sampler = VK_NULL_HANDLE;
+ }
+
+ if (m_texStaging) {
+ m_devFuncs->vkDestroyImage(dev, m_texStaging, nullptr);
+ m_texStaging = VK_NULL_HANDLE;
+ }
+
+ if (m_texStagingMem) {
+ m_devFuncs->vkFreeMemory(dev, m_texStagingMem, nullptr);
+ m_texStagingMem = VK_NULL_HANDLE;
+ }
+
+ if (m_texView) {
+ m_devFuncs->vkDestroyImageView(dev, m_texView, nullptr);
+ m_texView = VK_NULL_HANDLE;
+ }
+
+ if (m_texImage) {
+ m_devFuncs->vkDestroyImage(dev, m_texImage, nullptr);
+ m_texImage = VK_NULL_HANDLE;
+ }
+
+ if (m_texMem) {
+ m_devFuncs->vkFreeMemory(dev, m_texMem, nullptr);
+ m_texMem = VK_NULL_HANDLE;
+ }
+
+ if (m_pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_pipeline, nullptr);
+ m_pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_pipelineLayout, nullptr);
+ m_pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr);
+ m_descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr);
+ m_descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_buf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr);
+ m_buf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+}
+
+void VulkanRenderer::startNextFrame()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ // Add the necessary barriers and do the host-linear -> device-optimal copy, if not yet done.
+ ensureTexture();
+
+ VkClearColorValue clearColor = { 0, 0, 0, 1 };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[2];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem, m_uniformBufInfo[m_window->currentFrame()].offset,
+ UNIFORM_DATA_SIZE, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ QMatrix4x4 m = m_proj;
+ m.rotate(m_rotation, 0, 0, 1);
+ memcpy(p, m.constData(), 16 * sizeof(float));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Not exactly a real animation system, just advance on every frame for now.
+ m_rotation += 1.0f;
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1,
+ &m_descSet[m_window->currentFrame()], 0, nullptr);
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset);
+
+ VkViewport viewport;
+ viewport.x = viewport.y = 0;
+ viewport.width = sz.width();
+ viewport.height = sz.height();
+ viewport.minDepth = 0;
+ viewport.maxDepth = 1;
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor;
+ scissor.offset.x = scissor.offset.y = 0;
+ scissor.extent.width = viewport.width;
+ scissor.extent.height = viewport.height;
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ m_devFuncs->vkCmdDraw(cb, 4, 1, 0, 0);
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.h b/examples/vulkan/hellovulkantexture/hellovulkantexture.h
new file mode 100644
index 0000000000..a8c96d1987
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+#include <QImage>
+
+class VulkanRenderer : public QVulkanWindowRenderer
+{
+public:
+ VulkanRenderer(QVulkanWindow *w);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+private:
+ VkShaderModule createShader(const QString &name);
+ bool createTexture(const QString &name);
+ bool createTextureImage(const QSize &size, VkImage *image, VkDeviceMemory *mem,
+ VkImageTiling tiling, VkImageUsageFlags usage, uint32_t memIndex);
+ bool writeLinearImage(const QImage &img, VkImage image, VkDeviceMemory memory);
+ void ensureTexture();
+
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_buf = VK_NULL_HANDLE;
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkDescriptorPool m_descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout m_descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline m_pipeline = VK_NULL_HANDLE;
+
+ VkSampler m_sampler = VK_NULL_HANDLE;
+ VkImage m_texImage = VK_NULL_HANDLE;
+ VkDeviceMemory m_texMem = VK_NULL_HANDLE;
+ bool m_texLayoutPending = false;
+ VkImageView m_texView = VK_NULL_HANDLE;
+ VkImage m_texStaging = VK_NULL_HANDLE;
+ VkDeviceMemory m_texStagingMem = VK_NULL_HANDLE;
+ bool m_texStagingPending = false;
+ QSize m_texSize;
+ VkFormat m_texFormat;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0.0f;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.pro b/examples/vulkan/hellovulkantexture/hellovulkantexture.pro
new file mode 100644
index 0000000000..59bfcda715
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.pro
@@ -0,0 +1,7 @@
+HEADERS += hellovulkantexture.h
+SOURCES += hellovulkantexture.cpp main.cpp
+RESOURCES += hellovulkantexture.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkantexture
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc b/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc
new file mode 100644
index 0000000000..04e7cda859
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>texture_vert.spv</file>
+ <file>texture_frag.spv</file>
+ <file>qt256.png</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkantexture/main.cpp b/examples/vulkan/hellovulkantexture/main.cpp
new file mode 100644
index 0000000000..1144463b70
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/main.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "hellovulkantexture.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+ if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
+ w.setPreferredColorFormats(QVector<VkFormat>() << VK_FORMAT_B8G8R8A8_SRGB);
+
+ w.resize(1024, 768);
+ w.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkantexture/qt256.png b/examples/vulkan/hellovulkantexture/qt256.png
new file mode 100644
index 0000000000..30c621c9c6
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/qt256.png
Binary files differ
diff --git a/examples/vulkan/hellovulkantexture/texture.frag b/examples/vulkan/hellovulkantexture/texture.frag
new file mode 100644
index 0000000000..e6021fe905
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture.frag
@@ -0,0 +1,12 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D tex;
+
+void main()
+{
+ fragColor = texture(tex, v_texcoord);
+}
diff --git a/examples/vulkan/hellovulkantexture/texture.vert b/examples/vulkan/hellovulkantexture/texture.vert
new file mode 100644
index 0000000000..de486cb772
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_texcoord = texcoord;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/examples/vulkan/hellovulkantexture/texture_frag.spv b/examples/vulkan/hellovulkantexture/texture_frag.spv
new file mode 100644
index 0000000000..7521ef6eef
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkantexture/texture_vert.spv b/examples/vulkan/hellovulkantexture/texture_vert.spv
new file mode 100644
index 0000000000..6292c0de31
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro
new file mode 100644
index 0000000000..db016da3ac
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro
@@ -0,0 +1,12 @@
+HEADERS += \
+ ../shared/trianglerenderer.h
+
+SOURCES += \
+ main.cpp \
+ ../shared/trianglerenderer.cpp
+
+RESOURCES += hellovulkantriangle.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkantriangle
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc
new file mode 100644
index 0000000000..489fc7295a
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color_vert.spv">../shared/color_vert.spv</file>
+ <file alias="color_frag.spv">../shared/color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkantriangle/main.cpp b/examples/vulkan/hellovulkantriangle/main.cpp
new file mode 100644
index 0000000000..d3eef2e14a
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/main.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "../shared/trianglerenderer.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new TriangleRenderer(this, true); // try MSAA, when available
+}
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+
+ w.resize(1024, 768);
+ w.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
new file mode 100644
index 0000000000..81daa9bb96
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "hellovulkanwidget.h"
+#include <QVulkanFunctions>
+#include <QApplication>
+#include <QVBoxLayout>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QLCDNumber>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QTabWidget>
+
+MainWindow::MainWindow(VulkanWindow *w, QPlainTextEdit *logWidget)
+ : m_window(w)
+{
+ QWidget *wrapper = QWidget::createWindowContainer(w);
+
+ m_info = new QPlainTextEdit;
+ m_info->setReadOnly(true);
+
+ m_number = new QLCDNumber(3);
+ m_number->setSegmentStyle(QLCDNumber::Filled);
+
+ QPushButton *grabButton = new QPushButton(tr("&Grab"));
+ grabButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(grabButton, &QPushButton::clicked, this, &MainWindow::onGrabRequested);
+
+ QPushButton *quitButton = new QPushButton(tr("&Quit"));
+ quitButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(quitButton, &QPushButton::clicked, qApp, &QCoreApplication::quit);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ m_infoTab = new QTabWidget(this);
+ m_infoTab->addTab(m_info, tr("Vulkan Info"));
+ m_infoTab->addTab(logWidget, tr("Debug Log"));
+ layout->addWidget(m_infoTab, 2);
+ layout->addWidget(m_number, 1);
+ layout->addWidget(wrapper, 5);
+ layout->addWidget(grabButton, 1);
+ layout->addWidget(quitButton, 1);
+ setLayout(layout);
+}
+
+void MainWindow::onVulkanInfoReceived(const QString &text)
+{
+ m_info->setPlainText(text);
+}
+
+void MainWindow::onFrameQueued(int colorValue)
+{
+ m_number->display(colorValue);
+}
+
+void MainWindow::onGrabRequested()
+{
+ if (!m_window->supportsGrab()) {
+ QMessageBox::warning(this, tr("Cannot grab"), tr("This swapchain does not support readbacks."));
+ return;
+ }
+
+ QImage img = m_window->grab();
+
+ // Our startNextFrame() implementation is synchronous so img is ready to be
+ // used right here.
+
+ QFileDialog fd(this);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.setDefaultSuffix("png");
+ fd.selectFile("test.png");
+ if (fd.exec() == QDialog::Accepted)
+ img.save(fd.selectedFiles().first());
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(VulkanWindow *w)
+ : TriangleRenderer(w)
+{
+}
+
+void VulkanRenderer::initResources()
+{
+ TriangleRenderer::initResources();
+
+ QVulkanInstance *inst = m_window->vulkanInstance();
+ m_devFuncs = inst->deviceFunctions(m_window->device());
+
+ QString info;
+ info += QString().sprintf("Number of physical devices: %d\n", m_window->availablePhysicalDevices().count());
+
+ QVulkanFunctions *f = inst->functions();
+ VkPhysicalDeviceProperties props;
+ f->vkGetPhysicalDeviceProperties(m_window->physicalDevice(), &props);
+ info += QString().sprintf("Active physical device name: '%s' version %d.%d.%d\nAPI version %d.%d.%d\n",
+ props.deviceName,
+ VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion),
+ VK_VERSION_PATCH(props.driverVersion),
+ VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion),
+ VK_VERSION_PATCH(props.apiVersion));
+
+ info += QStringLiteral("Supported instance layers:\n");
+ for (const QVulkanLayer &layer : inst->supportedLayers())
+ info += QString().sprintf(" %s v%u\n", layer.name.constData(), layer.version);
+ info += QStringLiteral("Enabled instance layers:\n");
+ for (const QByteArray &layer : inst->layers())
+ info += QString().sprintf(" %s\n", layer.constData());
+
+ info += QStringLiteral("Supported instance extensions:\n");
+ for (const QVulkanExtension &ext : inst->supportedExtensions())
+ info += QString().sprintf(" %s v%u\n", ext.name.constData(), ext.version);
+ info += QStringLiteral("Enabled instance extensions:\n");
+ for (const QByteArray &ext : inst->extensions())
+ info += QString().sprintf(" %s\n", ext.constData());
+
+ info += QString().sprintf("Color format: %u\nDepth-stencil format: %u\n",
+ m_window->colorFormat(), m_window->depthStencilFormat());
+
+ info += QStringLiteral("Supported sample counts:");
+ const QVector<int> sampleCounts = m_window->supportedSampleCounts();
+ for (int count : sampleCounts)
+ info += QLatin1Char(' ') + QString::number(count);
+ info += QLatin1Char('\n');
+
+ emit static_cast<VulkanWindow *>(m_window)->vulkanInfoReceived(info);
+}
+
+void VulkanRenderer::startNextFrame()
+{
+ TriangleRenderer::startNextFrame();
+ emit static_cast<VulkanWindow *>(m_window)->frameQueued(int(m_rotation) % 360);
+}
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h
new file mode 100644
index 0000000000..e70d331ae8
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "../shared/trianglerenderer.h"
+#include <QWidget>
+
+class VulkanWindow;
+
+QT_BEGIN_NAMESPACE
+class QTabWidget;
+class QPlainTextEdit;
+class QLCDNumber;
+QT_END_NAMESPACE
+
+class MainWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(VulkanWindow *w, QPlainTextEdit *logWidget);
+
+public slots:
+ void onVulkanInfoReceived(const QString &text);
+ void onFrameQueued(int colorValue);
+ void onGrabRequested();
+
+private:
+ VulkanWindow *m_window;
+ QTabWidget *m_infoTab;
+ QPlainTextEdit *m_info;
+ QLCDNumber *m_number;
+};
+
+class VulkanRenderer : public TriangleRenderer
+{
+public:
+ VulkanRenderer(VulkanWindow *w);
+
+ void initResources() override;
+ void startNextFrame() override;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+ Q_OBJECT
+
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+
+signals:
+ void vulkanInfoReceived(const QString &text);
+ void frameQueued(int colorValue);
+};
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro
new file mode 100644
index 0000000000..7b87d7f210
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro
@@ -0,0 +1,16 @@
+QT += widgets
+
+HEADERS += \
+ hellovulkanwidget.h \
+ ../shared/trianglerenderer.h
+
+SOURCES += \
+ hellovulkanwidget.cpp \
+ main.cpp \
+ ../shared/trianglerenderer.cpp
+
+RESOURCES += hellovulkanwidget.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkanwidget
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc
new file mode 100644
index 0000000000..489fc7295a
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color_vert.spv">../shared/color_vert.spv</file>
+ <file alias="color_frag.spv">../shared/color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkanwidget/main.cpp b/examples/vulkan/hellovulkanwidget/main.cpp
new file mode 100644
index 0000000000..5ddaf90224
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/main.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QPlainTextEdit>
+#include <QVulkanInstance>
+#include <QLibraryInfo>
+#include <QLoggingCategory>
+#include <QPointer>
+#include "hellovulkanwidget.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+static QPointer<QPlainTextEdit> messageLogWidget;
+static QtMessageHandler oldMessageHandler = nullptr;
+
+static void messageHandler(QtMsgType msgType, const QMessageLogContext &logContext, const QString &text)
+{
+ if (!messageLogWidget.isNull())
+ messageLogWidget->appendPlainText(text);
+ if (oldMessageHandler)
+ oldMessageHandler(msgType, logContext, text);
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ messageLogWidget = new QPlainTextEdit(QLatin1String(QLibraryInfo::build()) + QLatin1Char('\n'));
+ messageLogWidget->setReadOnly(true);
+
+ oldMessageHandler = qInstallMessageHandler(messageHandler);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow *vulkanWindow = new VulkanWindow;
+ vulkanWindow->setVulkanInstance(&inst);
+
+ MainWindow mainWindow(vulkanWindow, messageLogWidget.data());
+ QObject::connect(vulkanWindow, &VulkanWindow::vulkanInfoReceived, &mainWindow, &MainWindow::onVulkanInfoReceived);
+ QObject::connect(vulkanWindow, &VulkanWindow::frameQueued, &mainWindow, &MainWindow::onFrameQueued);
+
+ mainWindow.resize(1024, 768);
+ mainWindow.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp
new file mode 100644
index 0000000000..0a7d1d4174
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "hellovulkanwindow.h"
+#include <QVulkanFunctions>
+
+//! [0]
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(QVulkanWindow *w)
+ : m_window(w)
+{
+}
+//! [0]
+
+//! [1]
+void VulkanRenderer::initResources()
+{
+ qDebug("initResources");
+
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device());
+}
+//! [1]
+
+void VulkanRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+}
+
+void VulkanRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void VulkanRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+}
+
+//! [2]
+void VulkanRenderer::startNextFrame()
+{
+ m_green += 0.005f;
+ if (m_green > 1.0f)
+ m_green = 0.0f;
+
+ VkClearColorValue clearColor = { 0.0f, m_green, 0.0f, 1.0f };
+ VkClearDepthStencilValue clearDS = { 1.0f, 0 };
+ VkClearValue clearValues[2];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ const QSize sz = m_window->swapChainImageSize();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ // Do nothing else. We will just clear to green, changing the component on
+ // every invocation. This also helps verifying the rate to which the thread
+ // is throttled to. (The elapsed time between startNextFrame calls should
+ // typically be around 16 ms. Note that rendering is 2 frames ahead of what
+ // is displayed.)
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
+//! [2]
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h
new file mode 100644
index 0000000000..5f52e402ca
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+
+//! [0]
+class VulkanRenderer : public QVulkanWindowRenderer
+{
+public:
+ VulkanRenderer(QVulkanWindow *w);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+private:
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+ float m_green = 0;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
+//! [0]
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro
new file mode 100644
index 0000000000..8f7d9494e2
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro
@@ -0,0 +1,6 @@
+HEADERS += hellovulkanwindow.h
+SOURCES += hellovulkanwindow.cpp main.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkanwindow
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkanwindow/main.cpp b/examples/vulkan/hellovulkanwindow/main.cpp
new file mode 100644
index 0000000000..313c28f9e0
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/main.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "hellovulkanwindow.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+//! [0]
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+//! [0]
+
+//! [1]
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+
+ w.resize(1024, 768);
+ w.show();
+//! [1]
+
+ return app.exec();
+}
diff --git a/examples/vulkan/shared/block.buf b/examples/vulkan/shared/block.buf
new file mode 100644
index 0000000000..28ec2620bd
--- /dev/null
+++ b/examples/vulkan/shared/block.buf
Binary files differ
diff --git a/examples/vulkan/shared/block.txt b/examples/vulkan/shared/block.txt
new file mode 100644
index 0000000000..a6b66b83cc
--- /dev/null
+++ b/examples/vulkan/shared/block.txt
@@ -0,0 +1,100 @@
+# Blender v2.78 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib block.mtl
+o Cube_Cube.001
+v 0.450000 -0.500000 -0.450000
+v 0.450000 -0.500000 0.450000
+v -0.450000 -0.500000 0.450000
+v -0.450000 -0.500000 -0.450000
+v -0.500000 0.450000 0.450000
+v -0.500000 0.450000 -0.450000
+v -0.500000 -0.450000 -0.450000
+v -0.500000 -0.450000 0.450000
+v -0.450000 0.500000 -0.450000
+v -0.450000 0.500000 0.450000
+v 0.450000 0.500000 0.450000
+v 0.450000 0.500000 -0.450000
+v -0.450000 0.450000 -0.500000
+v 0.450000 0.450000 -0.500000
+v 0.450000 -0.450000 -0.500000
+v -0.450000 -0.450000 -0.500000
+v 0.450000 0.450000 0.500000
+v -0.450000 0.450000 0.500000
+v -0.450000 -0.450000 0.500000
+v 0.450000 -0.450000 0.500000
+v 0.500000 -0.450000 -0.450000
+v 0.500000 0.450000 -0.450000
+v 0.500000 -0.450000 0.450000
+v 0.500000 0.450000 0.450000
+vn 0.0000 -1.0000 -0.0000
+vn -1.0000 0.0000 0.0000
+vn 0.0000 1.0000 0.0000
+vn 0.0000 0.0000 -1.0000
+vn 0.0000 -0.0000 1.0000
+vn 0.5774 -0.5773 -0.5774
+vn 0.5774 0.5774 -0.5774
+vn 0.5774 -0.5774 0.5774
+vn 0.5774 0.5773 0.5774
+vn -0.5774 -0.5773 -0.5774
+vn -0.5773 0.5774 -0.5774
+vn -0.5774 -0.5774 0.5774
+vn -0.5774 0.5773 0.5774
+vn 0.7071 0.0000 -0.7071
+vn 0.7071 0.7071 0.0000
+vn 0.7071 -0.0000 0.7071
+vn 0.7071 -0.7071 -0.0000
+vn 0.0000 0.7071 0.7071
+vn -0.7071 -0.0000 0.7071
+vn 0.0000 -0.7071 0.7071
+vn -0.7071 0.7071 0.0000
+vn -0.7071 0.0000 -0.7071
+vn -0.7071 -0.7071 -0.0000
+vn 0.0000 0.7071 -0.7071
+vn 0.0000 -0.7071 -0.7071
+vn 1.0000 0.0000 0.0000
+usemtl None
+s 1
+f 2//1 4//1 1//1
+f 6//2 8//2 5//2
+f 10//3 12//3 9//3
+f 14//4 16//4 13//4
+f 18//5 20//5 17//5
+f 15//6 21//6 1//6
+f 14//7 12//7 22//7
+f 20//8 2//8 23//8
+f 11//9 17//9 24//9
+f 16//10 4//10 7//10
+f 9//11 13//11 6//11
+f 8//12 3//12 19//12
+f 10//13 5//13 18//13
+f 14//14 21//14 15//14
+f 11//15 22//15 12//15
+f 20//16 24//16 17//16
+f 1//17 23//17 2//17
+f 10//18 17//18 11//18
+f 8//19 18//19 5//19
+f 2//20 19//20 3//20
+f 9//21 5//21 10//21
+f 16//22 6//22 13//22
+f 3//23 7//23 4//23
+f 12//24 13//24 9//24
+f 4//25 15//25 1//25
+f 24//26 21//26 22//26
+f 2//1 3//1 4//1
+f 6//2 7//2 8//2
+f 10//3 11//3 12//3
+f 14//4 15//4 16//4
+f 18//5 19//5 20//5
+f 14//14 22//14 21//14
+f 11//15 24//15 22//15
+f 20//16 23//16 24//16
+f 1//17 21//17 23//17
+f 10//18 18//18 17//18
+f 8//19 19//19 18//19
+f 2//20 20//20 19//20
+f 9//21 6//21 5//21
+f 16//22 7//22 6//22
+f 3//23 8//23 7//23
+f 12//24 14//24 13//24
+f 4//25 16//25 15//25
+f 24//26 23//26 21//26
diff --git a/examples/vulkan/shared/color.frag b/examples/vulkan/shared/color.frag
new file mode 100644
index 0000000000..375587662f
--- /dev/null
+++ b/examples/vulkan/shared/color.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec3 v_color;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(v_color, 1.0);
+}
diff --git a/examples/vulkan/shared/color.vert b/examples/vulkan/shared/color.vert
new file mode 100644
index 0000000000..02492c0e65
--- /dev/null
+++ b/examples/vulkan/shared/color.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 color;
+
+layout(location = 0) out vec3 v_color;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/examples/vulkan/shared/color_frag.spv b/examples/vulkan/shared/color_frag.spv
new file mode 100644
index 0000000000..30e33b76ca
--- /dev/null
+++ b/examples/vulkan/shared/color_frag.spv
Binary files differ
diff --git a/examples/vulkan/shared/color_vert.spv b/examples/vulkan/shared/color_vert.spv
new file mode 100644
index 0000000000..a1f42e3119
--- /dev/null
+++ b/examples/vulkan/shared/color_vert.spv
Binary files differ
diff --git a/examples/vulkan/shared/objconvert.js b/examples/vulkan/shared/objconvert.js
new file mode 100644
index 0000000000..9b49e3cdac
--- /dev/null
+++ b/examples/vulkan/shared/objconvert.js
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+var fs = require('fs');
+
+var metadata = {
+ vertexCount: 0,
+ aabb: [[null, null], [null, null], [null, null]],
+ emitVertex: function(v) {
+ ++metadata.vertexCount;
+ var aabb = metadata.aabb;
+ if (aabb[0][0] === null || v[0] < aabb[0][0]) // min x
+ aabb[0][0] = v[0];
+ if (aabb[0][1] === null || v[0] > aabb[0][1]) // max x
+ aabb[0][1] = v[0];
+ if (aabb[1][0] === null || v[1] < aabb[1][0]) // min y
+ aabb[1][0] = v[1];
+ if (aabb[1][1] === null || v[1] > aabb[1][1]) // max y
+ aabb[1][1] = v[1];
+ if (aabb[2][0] === null || v[2] < aabb[2][0]) // min z
+ aabb[2][0] = v[2];
+ if (aabb[2][1] === null || v[2] > aabb[2][1]) // max z
+ aabb[2][1] = v[2];
+ },
+ getBuffer: function() {
+ var aabb = metadata.aabb;
+ console.log(metadata.vertexCount + " vertices");
+ console.log("AABB: " + aabb[0][0] + ".." + aabb[0][1]
+ + ", " + aabb[1][0] + ".." + aabb[1][1]
+ + ", " + aabb[2][0] + ".." + aabb[2][1]);
+ var buf = new Buffer((2 + 6) * 4);
+ var format = 1, p = 0;
+ buf.writeUInt32LE(format, p++);
+ buf.writeUInt32LE(metadata.vertexCount, p++ * 4);
+ for (var i = 0; i < 3; ++i) {
+ buf.writeFloatLE(aabb[i][0], p++ * 4);
+ buf.writeFloatLE(aabb[i][1], p++ * 4);
+ }
+ return buf;
+ }
+};
+
+function makeVec(s, n) {
+ var v = [];
+ s.split(' ').forEach(function (coordStr) {
+ var coord = parseFloat(coordStr);
+ if (!isNaN(coord))
+ v.push(coord);
+ });
+ if (v.length != n) {
+ console.error("Wrong vector size, expected " + n + ", got " + v.length);
+ process.exit();
+ }
+ return v;
+}
+
+function parseObj(filename, callback) {
+ fs.readFile(filename, "ascii", function (err, data) {
+ if (err)
+ throw err;
+ var groupCount = 0;
+ var parsed = { 'vertices': [], 'normals': [], 'texcoords': [], 'links': [] };
+ var missingTexCount = 0, missingNormCount = 0;
+ data.split('\n').forEach(function (line) {
+ var s = line.trim();
+ if (!s.length || groupCount > 1)
+ return;
+ if (s[0] === '#')
+ return;
+ if (s[0] === 'g') {
+ ++groupCount;
+ } else if (s.substr(0, 2) === "v ") {
+ parsed.vertices.push(makeVec(s, 3));
+ } else if (s.substr(0, 3) === "vn ") {
+ parsed.normals.push(makeVec(s, 3));
+ } else if (s.substr(0, 3) === "vt ") {
+ parsed.texcoords.push(makeVec(s, 2));
+ } else if (s.substr(0, 2) === "f ") {
+ var refs = s.split(' ');
+ var vertCount = refs.length - 1;
+ if (vertCount != 3)
+ console.warn("Face " + parsed.links.length / 3 + " has " + vertCount + " vertices! (not triangulated?)");
+ for (var i = 1, ie = Math.min(4, refs.length); i < ie; ++i) {
+ var refComps = refs[i].split('/');
+ var vertIndex = parseInt(refComps[0]) - 1;
+ var texIndex = -1;
+ if (refComps.length >= 2 && refComps[1].length)
+ texIndex = parseInt(refComps[1]) - 1;
+ var normIndex = -1;
+ if (refComps.length >= 3 && refComps[2].length)
+ normIndex = parseInt(refComps[2]) - 1;
+ parsed.links.push([vertIndex, texIndex, normIndex]);
+ if (texIndex == -1)
+ ++missingTexCount;
+ if (normIndex == -1)
+ ++missingNormCount;
+ }
+ }
+ });
+ console.log(missingTexCount + " missing texture coordinates, " + missingNormCount + " missing normals");
+ callback(parsed);
+ });
+}
+
+function fillVert(src, index, dst, elemCount, isVertexCoord) {
+ var vertex = [];
+ if (index >= 0) {
+ for (var i = 0; i < elemCount; ++i) {
+ var elem = src[index][i];
+ if (isVertexCoord)
+ vertex.push(elem);
+ dst.buf.writeFloatLE(elem, dst.bufptr++ * 4);
+ }
+ if (vertex.length == 3)
+ metadata.emitVertex(vertex);
+ } else {
+ if (isVertexCoord) {
+ console.error("Missing vertex");
+ process.exit();
+ }
+ for (var i = 0; i < elemCount; ++i)
+ dst.buf.writeFloatLE(0, dst.bufptr++ * 4);
+ }
+ return vertex;
+}
+
+function normalize(v) {
+ var len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
+ if (len == 0.0 || len == 1.0)
+ return;
+ len = Math.sqrt(len);
+ return [ v[0] / len, v[1] / len, v[2] / len ];
+}
+
+function surfaceNormal(a, b, c) {
+ var u = [ b[0] - a[0], b[1] - a[1], b[2] - a[2] ];
+ var v = [ c[0] - a[0], c[1] - a[1], c[2] - a[2] ];
+ var result = [ u[1] * v[2] - u[2] * v[1],
+ u[2] * v[0] - u[0] * v[2],
+ u[0] * v[1] - u[1] * v[0] ];
+ return normalize(result);
+}
+
+function objDataToBuf(parsed) {
+ var floatCount = parsed.links.length * (3 + 2 + 3);
+ var buf = new Buffer(floatCount * 4);
+ var dst = { 'buf': buf, 'bufptr': 0 };
+ var tri = [];
+ var genNormals = false;
+ var genNormCount = 0;
+ for (var i = 0; i < parsed.links.length; ++i) {
+ var link = parsed.links[i];
+ var vertIndex = link[0], texIndex = link[1], normIndex = link[2];
+ tri.push(fillVert(parsed.vertices, vertIndex, dst, 3, true));
+ fillVert(parsed.texcoords, texIndex, dst, 2);
+ fillVert(parsed.normals, normIndex, dst, 3);
+ if (normIndex == -1)
+ genNormals = true;
+ if (tri.length == 3) {
+ if (genNormals) {
+ var norm = surfaceNormal(tri[0], tri[1], tri[2]);
+ for (var nvIdx = 0; nvIdx < 3; ++nvIdx) {
+ dst.buf.writeFloatLE(norm[0], (dst.bufptr - 3 - nvIdx * 8) * 4);
+ dst.buf.writeFloatLE(norm[1], (dst.bufptr - 2 - nvIdx * 8) * 4);
+ dst.buf.writeFloatLE(norm[2], (dst.bufptr - 1 - nvIdx * 8) * 4);
+ }
+ genNormCount += 3;
+ }
+ tri = [];
+ }
+ }
+ if (genNormCount)
+ console.log("Generated " + genNormCount + " normals");
+ return buf;
+}
+
+var inFilename = process.argv[2];
+var outFilename = process.argv[3];
+
+if (process.argv.length < 4) {
+ console.log("Usage: objconvert file.obj file.buf");
+ process.exit();
+}
+
+parseObj(inFilename, function (parsed) {
+ var buf = objDataToBuf(parsed);
+ var f = fs.createWriteStream(outFilename);
+ f.on("error", function (e) { console.error(e); });
+ f.write(metadata.getBuffer());
+ f.write(buf);
+ f.end();
+ console.log("Written to " + outFilename + ", format is:");
+ console.log(" uint32 version, uint32 vertex_count, float32 aabb[6], vertex_count * (float32 vertex[3], float32 texcoord[2], float32 normal[3])");
+});
diff --git a/examples/vulkan/shared/qt_logo.buf b/examples/vulkan/shared/qt_logo.buf
new file mode 100644
index 0000000000..316ec41aee
--- /dev/null
+++ b/examples/vulkan/shared/qt_logo.buf
Binary files differ
diff --git a/examples/vulkan/shared/qt_logo.txt b/examples/vulkan/shared/qt_logo.txt
new file mode 100644
index 0000000000..167b8a4caf
--- /dev/null
+++ b/examples/vulkan/shared/qt_logo.txt
@@ -0,0 +1,2912 @@
+# Blender v2.77 (sub 0) OBJ File: 'qt_logo.blend'
+# www.blender.org
+o qt_logo_qt_logo_mesh
+v 0.500000 0.030000 -0.271909
+v 0.500000 0.030000 -0.234087
+v 0.500000 0.030000 0.229669
+v 0.361282 0.030000 0.368353
+v -0.369121 0.030000 0.368353
+v -0.403885 0.030000 0.368353
+v -0.500000 0.030000 0.368353
+v -0.500000 0.030000 0.272263
+v -0.500000 0.030000 0.234440
+v -0.500000 0.030000 -0.229316
+v -0.361282 0.030000 -0.368000
+v 0.369121 0.030000 -0.368000
+v 0.403886 0.030000 -0.368000
+v 0.500000 0.030000 -0.368000
+v -0.014123 0.030000 0.177038
+v -0.008432 0.030000 0.172481
+v -0.003036 0.030000 0.167611
+v 0.002070 0.030000 0.162429
+v 0.006887 0.030000 0.156934
+v 0.011418 0.030000 0.151127
+v 0.015664 0.030000 0.145008
+v 0.019629 0.030000 0.138577
+v 0.023315 0.030000 0.131833
+v 0.026724 0.030000 0.124776
+v 0.029858 0.030000 0.117408
+v 0.032720 0.030000 0.109727
+v 0.035255 0.030000 0.101769
+v 0.037575 0.030000 0.093399
+v 0.039680 0.030000 0.084618
+v 0.041569 0.030000 0.075425
+v 0.043240 0.030000 0.065820
+v 0.044692 0.030000 0.055804
+v 0.045923 0.030000 0.045375
+v 0.046934 0.030000 0.034535
+v 0.047722 0.030000 0.023284
+v 0.048286 0.030000 0.011620
+v 0.048626 0.030000 -0.000455
+v 0.048739 0.030000 -0.012942
+v 0.048469 0.030000 -0.031775
+v 0.047658 0.030000 -0.049771
+v 0.046305 0.030000 -0.066929
+v 0.044409 0.030000 -0.083249
+v 0.041969 0.030000 -0.098732
+v 0.038983 0.030000 -0.113377
+v 0.035450 0.030000 -0.127184
+v 0.031369 0.030000 -0.140154
+v 0.026739 0.030000 -0.152286
+v 0.021559 0.030000 -0.163580
+v 0.015828 0.030000 -0.174037
+v 0.009543 0.030000 -0.183656
+v 0.002656 0.030000 -0.192551
+v -0.005054 0.030000 -0.200667
+v -0.013585 0.030000 -0.208004
+v -0.022937 0.030000 -0.214563
+v -0.033107 0.030000 -0.220347
+v -0.044095 0.030000 -0.225355
+v -0.055900 0.030000 -0.229590
+v -0.068520 0.030000 -0.233052
+v -0.081954 0.030000 -0.235742
+v -0.096201 0.030000 -0.237663
+v -0.111260 0.030000 -0.238814
+v -0.127130 0.030000 -0.239198
+v -0.143000 0.030000 -0.238808
+v -0.158061 0.030000 -0.237638
+v -0.172312 0.030000 -0.235689
+v -0.185753 0.030000 -0.232963
+v -0.198385 0.030000 -0.229461
+v -0.210208 0.030000 -0.225185
+v -0.221221 0.030000 -0.220134
+v -0.231425 0.030000 -0.214311
+v -0.240819 0.030000 -0.207716
+v -0.249404 0.030000 -0.200351
+v -0.257179 0.030000 -0.192217
+v -0.264144 0.030000 -0.183315
+v -0.270435 0.030000 -0.173618
+v -0.276186 0.030000 -0.163098
+v -0.281394 0.030000 -0.151754
+v -0.286059 0.030000 -0.139586
+v -0.290179 0.030000 -0.126595
+v -0.293754 0.030000 -0.112781
+v -0.296782 0.030000 -0.098143
+v -0.299263 0.030000 -0.082682
+v -0.301194 0.030000 -0.066397
+v -0.302575 0.030000 -0.049288
+v -0.303404 0.030000 -0.031357
+v -0.303681 0.030000 -0.012601
+v -0.303411 0.030000 0.006061
+v -0.302602 0.030000 0.023884
+v -0.301253 0.030000 0.040864
+v -0.299364 0.030000 0.056999
+v -0.296935 0.030000 0.072288
+v -0.293967 0.030000 0.086726
+v -0.290460 0.030000 0.100313
+v -0.286412 0.030000 0.113046
+v -0.281825 0.030000 0.124922
+v -0.276698 0.030000 0.135939
+v -0.271032 0.030000 0.146095
+v -0.264826 0.030000 0.155387
+v -0.257932 0.030000 0.163877
+v -0.250200 0.030000 0.171629
+v -0.241634 0.030000 0.178643
+v -0.232233 0.030000 0.184918
+v -0.221998 0.030000 0.190455
+v -0.210932 0.030000 0.195254
+v -0.199035 0.030000 0.199315
+v -0.186309 0.030000 0.202637
+v -0.172754 0.030000 0.205221
+v -0.158371 0.030000 0.207067
+v -0.143163 0.030000 0.208174
+v -0.127130 0.030000 0.208543
+v -0.122805 0.030000 0.208515
+v -0.118691 0.030000 0.208431
+v -0.114786 0.030000 0.208293
+v -0.111086 0.030000 0.208101
+v -0.107590 0.030000 0.207858
+v -0.104294 0.030000 0.207563
+v -0.101198 0.030000 0.207219
+v -0.098298 0.030000 0.206827
+v -0.095593 0.030000 0.206387
+v -0.093079 0.030000 0.205901
+v -0.090754 0.030000 0.205370
+v -0.088616 0.030000 0.204795
+v -0.032379 0.030000 0.297137
+v 0.032720 0.030000 0.266811
+v 0.027981 0.030000 0.259139
+v 0.022692 0.030000 0.250576
+v 0.017036 0.030000 0.241420
+v 0.011197 0.030000 0.231966
+v 0.005358 0.030000 0.222513
+v -0.000298 0.030000 0.213356
+v -0.005587 0.030000 0.204794
+v -0.010326 0.030000 0.197122
+v -0.014331 0.030000 0.190638
+v -0.017419 0.030000 0.185639
+v -0.019406 0.030000 0.182422
+v -0.020109 0.030000 0.181283
+v 0.291411 0.030000 0.137327
+v 0.286764 0.030000 0.137511
+v 0.281577 0.030000 0.137715
+v 0.276031 0.030000 0.137934
+v 0.270305 0.030000 0.138160
+v 0.264578 0.030000 0.138386
+v 0.259032 0.030000 0.138605
+v 0.253845 0.030000 0.138810
+v 0.249198 0.030000 0.138993
+v 0.245271 0.030000 0.139148
+v 0.242243 0.030000 0.139267
+v 0.240294 0.030000 0.139344
+v 0.239605 0.030000 0.139372
+v 0.235884 0.030000 0.139286
+v 0.232394 0.030000 0.139029
+v 0.229135 0.030000 0.138600
+v 0.226110 0.030000 0.137996
+v 0.223322 0.030000 0.137217
+v 0.220774 0.030000 0.136262
+v 0.218466 0.030000 0.135130
+v 0.216403 0.030000 0.133819
+v 0.214585 0.030000 0.132328
+v 0.213017 0.030000 0.130656
+v 0.211699 0.030000 0.128802
+v 0.210634 0.030000 0.126764
+v 0.209732 0.030000 0.124535
+v 0.208903 0.030000 0.121937
+v 0.208147 0.030000 0.118969
+v 0.207465 0.030000 0.115633
+v 0.206860 0.030000 0.111927
+v 0.206331 0.030000 0.107853
+v 0.205880 0.030000 0.103409
+v 0.205509 0.030000 0.098596
+v 0.205218 0.030000 0.093413
+v 0.205009 0.030000 0.087862
+v 0.204882 0.030000 0.081942
+v 0.204840 0.030000 0.075652
+v 0.204840 0.030000 -0.063713
+v 0.292093 0.030000 -0.063713
+v 0.292093 0.030000 -0.122662
+v 0.204840 0.030000 -0.122662
+v 0.204840 0.030000 -0.214664
+v 0.136333 0.030000 -0.214664
+v 0.136333 0.030000 -0.122662
+v 0.087935 0.030000 -0.122662
+v 0.087935 0.030000 -0.064054
+v 0.136333 0.030000 -0.064054
+v 0.136333 0.030000 -0.050850
+v 0.136333 0.030000 -0.036113
+v 0.136333 0.030000 -0.020353
+v 0.136333 0.030000 -0.004083
+v 0.136333 0.030000 0.012188
+v 0.136333 0.030000 0.027947
+v 0.136333 0.030000 0.042685
+v 0.136333 0.030000 0.055889
+v 0.136333 0.030000 0.067048
+v 0.136333 0.030000 0.075652
+v 0.136333 0.030000 0.081189
+v 0.136333 0.030000 0.083148
+v 0.136475 0.030000 0.094258
+v 0.136899 0.030000 0.104757
+v 0.137605 0.030000 0.114646
+v 0.138592 0.030000 0.123924
+v 0.139858 0.030000 0.132592
+v 0.141403 0.030000 0.140649
+v 0.143224 0.030000 0.148096
+v 0.145321 0.030000 0.154932
+v 0.147692 0.030000 0.161158
+v 0.150337 0.030000 0.166773
+v 0.153254 0.030000 0.171778
+v 0.156442 0.030000 0.176172
+v 0.159999 0.030000 0.180091
+v 0.164025 0.030000 0.183669
+v 0.168520 0.030000 0.186906
+v 0.173483 0.030000 0.189802
+v 0.178915 0.030000 0.192358
+v 0.184816 0.030000 0.194573
+v 0.191185 0.030000 0.196447
+v 0.198023 0.030000 0.197980
+v 0.205330 0.030000 0.199173
+v 0.213105 0.030000 0.200024
+v 0.221349 0.030000 0.200536
+v 0.230061 0.030000 0.200706
+v 0.233945 0.030000 0.200649
+v 0.238099 0.030000 0.200479
+v 0.242523 0.030000 0.200195
+v 0.247217 0.030000 0.199797
+v 0.252180 0.030000 0.199286
+v 0.257413 0.030000 0.198662
+v 0.262916 0.030000 0.197923
+v 0.268689 0.030000 0.197071
+v 0.274732 0.030000 0.196106
+v 0.281044 0.030000 0.195027
+v 0.287626 0.030000 0.193834
+v 0.294479 0.030000 0.192528
+v -0.042504 0.030000 -0.131451
+v -0.039308 0.030000 -0.123910
+v -0.036421 0.030000 -0.115714
+v -0.033843 0.030000 -0.106862
+v -0.031573 0.030000 -0.097352
+v -0.029610 0.030000 -0.087182
+v -0.027952 0.030000 -0.076353
+v -0.026597 0.030000 -0.064862
+v -0.025546 0.030000 -0.052708
+v -0.024797 0.030000 -0.039891
+v -0.024348 0.030000 -0.026409
+v -0.024199 0.030000 -0.012261
+v -0.024348 0.030000 0.001795
+v -0.024794 0.030000 0.015166
+v -0.025536 0.030000 0.027852
+v -0.026572 0.030000 0.039848
+v -0.027902 0.030000 0.051154
+v -0.029525 0.030000 0.061767
+v -0.031438 0.030000 0.071683
+v -0.033641 0.030000 0.080902
+v -0.036133 0.030000 0.089420
+v -0.038913 0.030000 0.097236
+v -0.041979 0.030000 0.104346
+v -0.045331 0.030000 0.110749
+v -0.049179 0.030000 0.116548
+v -0.053569 0.030000 0.121850
+v -0.058501 0.030000 0.126652
+v -0.063975 0.030000 0.130954
+v -0.069995 0.030000 0.134754
+v -0.076559 0.030000 0.138051
+v -0.083671 0.030000 0.140844
+v -0.091330 0.030000 0.143132
+v -0.099539 0.030000 0.144914
+v -0.108298 0.030000 0.146188
+v -0.117608 0.030000 0.146953
+v -0.127471 0.030000 0.147209
+v -0.137341 0.030000 0.146947
+v -0.146670 0.030000 0.146161
+v -0.155456 0.030000 0.144855
+v -0.163700 0.030000 0.143031
+v -0.171399 0.030000 0.140692
+v -0.178553 0.030000 0.137838
+v -0.185160 0.030000 0.134474
+v -0.191219 0.030000 0.130601
+v -0.196729 0.030000 0.126221
+v -0.201689 0.030000 0.121337
+v -0.206097 0.030000 0.115952
+v -0.209952 0.030000 0.110067
+v -0.213382 0.030000 0.103587
+v -0.216513 0.030000 0.096412
+v -0.219346 0.030000 0.088547
+v -0.221881 0.030000 0.079993
+v -0.224118 0.030000 0.070753
+v -0.226057 0.030000 0.060830
+v -0.227697 0.030000 0.050224
+v -0.229039 0.030000 0.038940
+v -0.230083 0.030000 0.026978
+v -0.230828 0.030000 0.014343
+v -0.231276 0.030000 0.001035
+v -0.231425 0.030000 -0.012942
+v -0.231269 0.030000 -0.027005
+v -0.230801 0.030000 -0.040404
+v -0.230024 0.030000 -0.053140
+v -0.228938 0.030000 -0.065215
+v -0.227544 0.030000 -0.076633
+v -0.225844 0.030000 -0.087395
+v -0.223838 0.030000 -0.097504
+v -0.221528 0.030000 -0.106963
+v -0.218915 0.030000 -0.115773
+v -0.216000 0.030000 -0.123937
+v -0.212785 0.030000 -0.131458
+v -0.209271 0.030000 -0.138337
+v -0.205266 0.030000 -0.144620
+v -0.200750 0.030000 -0.150350
+v -0.195723 0.030000 -0.155529
+v -0.190184 0.030000 -0.160157
+v -0.184134 0.030000 -0.164237
+v -0.177573 0.030000 -0.167769
+v -0.170501 0.030000 -0.170754
+v -0.162917 0.030000 -0.173194
+v -0.154823 0.030000 -0.175090
+v -0.146217 0.030000 -0.176442
+v -0.137100 0.030000 -0.177253
+v -0.127471 0.030000 -0.177523
+v -0.117843 0.030000 -0.177253
+v -0.108727 0.030000 -0.176442
+v -0.100125 0.030000 -0.175090
+v -0.092037 0.030000 -0.173194
+v -0.084466 0.030000 -0.170754
+v -0.077411 0.030000 -0.167769
+v -0.070875 0.030000 -0.164237
+v -0.064859 0.030000 -0.160157
+v -0.059363 0.030000 -0.155529
+v -0.054389 0.030000 -0.150350
+v -0.049939 0.030000 -0.144620
+v -0.046012 0.030000 -0.138337
+v 0.500000 -0.030000 -0.271909
+v 0.500000 -0.030000 -0.234087
+v 0.500000 -0.030000 0.229669
+v 0.361282 -0.030000 0.368353
+v -0.369121 -0.030000 0.368353
+v -0.403885 -0.030000 0.368353
+v -0.500000 -0.030000 0.368353
+v -0.500000 -0.030000 0.272263
+v -0.500000 -0.030000 0.234440
+v -0.500000 -0.030000 -0.229316
+v -0.361282 -0.030000 -0.368000
+v 0.369121 -0.030000 -0.368000
+v 0.403886 -0.030000 -0.368000
+v 0.500000 -0.030000 -0.368000
+v -0.014123 -0.030000 0.177038
+v -0.008432 -0.030000 0.172481
+v -0.003036 -0.030000 0.167611
+v 0.002070 -0.030000 0.162429
+v 0.006887 -0.030000 0.156934
+v 0.011418 -0.030000 0.151127
+v 0.015664 -0.030000 0.145008
+v 0.019629 -0.030000 0.138577
+v 0.023315 -0.030000 0.131833
+v 0.026724 -0.030000 0.124776
+v 0.029858 -0.030000 0.117408
+v 0.032720 -0.030000 0.109727
+v 0.035255 -0.030000 0.101769
+v 0.037575 -0.030000 0.093399
+v 0.039680 -0.030000 0.084618
+v 0.041569 -0.030000 0.075425
+v 0.043240 -0.030000 0.065820
+v 0.044692 -0.030000 0.055804
+v 0.045923 -0.030000 0.045375
+v 0.046934 -0.030000 0.034535
+v 0.047722 -0.030000 0.023284
+v 0.048286 -0.030000 0.011620
+v 0.048626 -0.030000 -0.000455
+v 0.048739 -0.030000 -0.012942
+v 0.048469 -0.030000 -0.031775
+v 0.047658 -0.030000 -0.049771
+v 0.046305 -0.030000 -0.066929
+v 0.044409 -0.030000 -0.083249
+v 0.041969 -0.030000 -0.098732
+v 0.038983 -0.030000 -0.113377
+v 0.035450 -0.030000 -0.127184
+v 0.031369 -0.030000 -0.140154
+v 0.026739 -0.030000 -0.152286
+v 0.021559 -0.030000 -0.163580
+v 0.015828 -0.030000 -0.174037
+v 0.009543 -0.030000 -0.183656
+v 0.002656 -0.030000 -0.192551
+v -0.005054 -0.030000 -0.200667
+v -0.013585 -0.030000 -0.208004
+v -0.022937 -0.030000 -0.214563
+v -0.033107 -0.030000 -0.220347
+v -0.044095 -0.030000 -0.225355
+v -0.055900 -0.030000 -0.229590
+v -0.068520 -0.030000 -0.233052
+v -0.081954 -0.030000 -0.235742
+v -0.096201 -0.030000 -0.237663
+v -0.111260 -0.030000 -0.238814
+v -0.127130 -0.030000 -0.239198
+v -0.143000 -0.030000 -0.238808
+v -0.158061 -0.030000 -0.237638
+v -0.172312 -0.030000 -0.235689
+v -0.185753 -0.030000 -0.232963
+v -0.198385 -0.030000 -0.229461
+v -0.210208 -0.030000 -0.225185
+v -0.221221 -0.030000 -0.220134
+v -0.231425 -0.030000 -0.214311
+v -0.240819 -0.030000 -0.207716
+v -0.249404 -0.030000 -0.200351
+v -0.257179 -0.030000 -0.192217
+v -0.264144 -0.030000 -0.183315
+v -0.270435 -0.030000 -0.173618
+v -0.276186 -0.030000 -0.163098
+v -0.281394 -0.030000 -0.151754
+v -0.286059 -0.030000 -0.139586
+v -0.290179 -0.030000 -0.126595
+v -0.293754 -0.030000 -0.112781
+v -0.296782 -0.030000 -0.098143
+v -0.299263 -0.030000 -0.082682
+v -0.301194 -0.030000 -0.066397
+v -0.302575 -0.030000 -0.049288
+v -0.303404 -0.030000 -0.031357
+v -0.303681 -0.030000 -0.012601
+v -0.303411 -0.030000 0.006061
+v -0.302602 -0.030000 0.023884
+v -0.301253 -0.030000 0.040864
+v -0.299364 -0.030000 0.056999
+v -0.296935 -0.030000 0.072288
+v -0.293967 -0.030000 0.086726
+v -0.290460 -0.030000 0.100313
+v -0.286412 -0.030000 0.113046
+v -0.281825 -0.030000 0.124922
+v -0.276698 -0.030000 0.135939
+v -0.271032 -0.030000 0.146095
+v -0.264826 -0.030000 0.155387
+v -0.257932 -0.030000 0.163877
+v -0.250200 -0.030000 0.171629
+v -0.241634 -0.030000 0.178643
+v -0.232233 -0.030000 0.184918
+v -0.221998 -0.030000 0.190455
+v -0.210932 -0.030000 0.195254
+v -0.199035 -0.030000 0.199315
+v -0.186309 -0.030000 0.202637
+v -0.172754 -0.030000 0.205221
+v -0.158371 -0.030000 0.207067
+v -0.143163 -0.030000 0.208174
+v -0.127130 -0.030000 0.208543
+v -0.122805 -0.030000 0.208515
+v -0.118691 -0.030000 0.208431
+v -0.114786 -0.030000 0.208293
+v -0.111086 -0.030000 0.208101
+v -0.107590 -0.030000 0.207858
+v -0.104294 -0.030000 0.207563
+v -0.101198 -0.030000 0.207219
+v -0.098298 -0.030000 0.206827
+v -0.095593 -0.030000 0.206387
+v -0.093079 -0.030000 0.205901
+v -0.090754 -0.030000 0.205370
+v -0.088616 -0.030000 0.204795
+v -0.032379 -0.030000 0.297137
+v 0.032720 -0.030000 0.266811
+v 0.027981 -0.030000 0.259139
+v 0.022692 -0.030000 0.250576
+v 0.017036 -0.030000 0.241420
+v 0.011197 -0.030000 0.231966
+v 0.005358 -0.030000 0.222513
+v -0.000298 -0.030000 0.213356
+v -0.005587 -0.030000 0.204794
+v -0.010326 -0.030000 0.197122
+v -0.014331 -0.030000 0.190638
+v -0.017419 -0.030000 0.185639
+v -0.019406 -0.030000 0.182422
+v -0.020109 -0.030000 0.181283
+v 0.291411 -0.030000 0.137327
+v 0.286764 -0.030000 0.137511
+v 0.281577 -0.030000 0.137715
+v 0.276031 -0.030000 0.137934
+v 0.270305 -0.030000 0.138160
+v 0.264578 -0.030000 0.138386
+v 0.259032 -0.030000 0.138605
+v 0.253845 -0.030000 0.138810
+v 0.249198 -0.030000 0.138993
+v 0.245271 -0.030000 0.139148
+v 0.242243 -0.030000 0.139267
+v 0.240294 -0.030000 0.139344
+v 0.239605 -0.030000 0.139372
+v 0.235884 -0.030000 0.139286
+v 0.232394 -0.030000 0.139029
+v 0.229135 -0.030000 0.138600
+v 0.226110 -0.030000 0.137996
+v 0.223322 -0.030000 0.137217
+v 0.220774 -0.030000 0.136262
+v 0.218466 -0.030000 0.135130
+v 0.216403 -0.030000 0.133819
+v 0.214585 -0.030000 0.132328
+v 0.213017 -0.030000 0.130656
+v 0.211699 -0.030000 0.128802
+v 0.210634 -0.030000 0.126764
+v 0.209732 -0.030000 0.124535
+v 0.208903 -0.030000 0.121937
+v 0.208147 -0.030000 0.118969
+v 0.207465 -0.030000 0.115633
+v 0.206860 -0.030000 0.111927
+v 0.206331 -0.030000 0.107853
+v 0.205880 -0.030000 0.103409
+v 0.205509 -0.030000 0.098596
+v 0.205218 -0.030000 0.093413
+v 0.205009 -0.030000 0.087862
+v 0.204882 -0.030000 0.081942
+v 0.204840 -0.030000 0.075652
+v 0.204840 -0.030000 -0.063713
+v 0.292093 -0.030000 -0.063713
+v 0.292093 -0.030000 -0.122662
+v 0.204840 -0.030000 -0.122662
+v 0.204840 -0.030000 -0.214664
+v 0.136333 -0.030000 -0.214664
+v 0.136333 -0.030000 -0.122662
+v 0.087935 -0.030000 -0.122662
+v 0.087935 -0.030000 -0.064054
+v 0.136333 -0.030000 -0.064054
+v 0.136333 -0.030000 -0.050850
+v 0.136333 -0.030000 -0.036113
+v 0.136333 -0.030000 -0.020353
+v 0.136333 -0.030000 -0.004083
+v 0.136333 -0.030000 0.012188
+v 0.136333 -0.030000 0.027947
+v 0.136333 -0.030000 0.042685
+v 0.136333 -0.030000 0.055889
+v 0.136333 -0.030000 0.067048
+v 0.136333 -0.030000 0.075652
+v 0.136333 -0.030000 0.081189
+v 0.136333 -0.030000 0.083148
+v 0.136475 -0.030000 0.094258
+v 0.136899 -0.030000 0.104757
+v 0.137605 -0.030000 0.114646
+v 0.138592 -0.030000 0.123924
+v 0.139858 -0.030000 0.132592
+v 0.141403 -0.030000 0.140649
+v 0.143224 -0.030000 0.148096
+v 0.145321 -0.030000 0.154932
+v 0.147692 -0.030000 0.161158
+v 0.150337 -0.030000 0.166773
+v 0.153254 -0.030000 0.171778
+v 0.156442 -0.030000 0.176172
+v 0.159999 -0.030000 0.180091
+v 0.164025 -0.030000 0.183669
+v 0.168520 -0.030000 0.186906
+v 0.173483 -0.030000 0.189802
+v 0.178915 -0.030000 0.192358
+v 0.184816 -0.030000 0.194573
+v 0.191185 -0.030000 0.196447
+v 0.198023 -0.030000 0.197980
+v 0.205330 -0.030000 0.199173
+v 0.213105 -0.030000 0.200024
+v 0.221349 -0.030000 0.200536
+v 0.230061 -0.030000 0.200706
+v 0.233945 -0.030000 0.200649
+v 0.238099 -0.030000 0.200479
+v 0.242523 -0.030000 0.200195
+v 0.247217 -0.030000 0.199797
+v 0.252180 -0.030000 0.199286
+v 0.257413 -0.030000 0.198662
+v 0.262916 -0.030000 0.197923
+v 0.268689 -0.030000 0.197071
+v 0.274732 -0.030000 0.196106
+v 0.281044 -0.030000 0.195027
+v 0.287626 -0.030000 0.193834
+v 0.294479 -0.030000 0.192528
+v -0.042504 -0.030000 -0.131451
+v -0.039308 -0.030000 -0.123910
+v -0.036421 -0.030000 -0.115714
+v -0.033843 -0.030000 -0.106862
+v -0.031573 -0.030000 -0.097352
+v -0.029610 -0.030000 -0.087182
+v -0.027952 -0.030000 -0.076353
+v -0.026597 -0.030000 -0.064862
+v -0.025546 -0.030000 -0.052708
+v -0.024797 -0.030000 -0.039891
+v -0.024348 -0.030000 -0.026409
+v -0.024199 -0.030000 -0.012261
+v -0.024348 -0.030000 0.001795
+v -0.024794 -0.030000 0.015166
+v -0.025536 -0.030000 0.027852
+v -0.026572 -0.030000 0.039848
+v -0.027902 -0.030000 0.051154
+v -0.029525 -0.030000 0.061767
+v -0.031438 -0.030000 0.071683
+v -0.033641 -0.030000 0.080902
+v -0.036133 -0.030000 0.089420
+v -0.038913 -0.030000 0.097236
+v -0.041979 -0.030000 0.104346
+v -0.045331 -0.030000 0.110749
+v -0.049179 -0.030000 0.116548
+v -0.053569 -0.030000 0.121850
+v -0.058501 -0.030000 0.126652
+v -0.063975 -0.030000 0.130954
+v -0.069995 -0.030000 0.134754
+v -0.076559 -0.030000 0.138051
+v -0.083671 -0.030000 0.140844
+v -0.091330 -0.030000 0.143132
+v -0.099539 -0.030000 0.144914
+v -0.108298 -0.030000 0.146188
+v -0.117608 -0.030000 0.146953
+v -0.127471 -0.030000 0.147209
+v -0.137341 -0.030000 0.146947
+v -0.146670 -0.030000 0.146161
+v -0.155456 -0.030000 0.144855
+v -0.163700 -0.030000 0.143031
+v -0.171399 -0.030000 0.140692
+v -0.178553 -0.030000 0.137838
+v -0.185160 -0.030000 0.134474
+v -0.191219 -0.030000 0.130601
+v -0.196729 -0.030000 0.126221
+v -0.201689 -0.030000 0.121337
+v -0.206097 -0.030000 0.115952
+v -0.209952 -0.030000 0.110067
+v -0.213382 -0.030000 0.103587
+v -0.216513 -0.030000 0.096412
+v -0.219346 -0.030000 0.088547
+v -0.221881 -0.030000 0.079993
+v -0.224118 -0.030000 0.070753
+v -0.226057 -0.030000 0.060830
+v -0.227697 -0.030000 0.050224
+v -0.229039 -0.030000 0.038940
+v -0.230083 -0.030000 0.026978
+v -0.230828 -0.030000 0.014343
+v -0.231276 -0.030000 0.001035
+v -0.231425 -0.030000 -0.012942
+v -0.231269 -0.030000 -0.027005
+v -0.230801 -0.030000 -0.040404
+v -0.230024 -0.030000 -0.053140
+v -0.228938 -0.030000 -0.065215
+v -0.227544 -0.030000 -0.076633
+v -0.225844 -0.030000 -0.087395
+v -0.223838 -0.030000 -0.097504
+v -0.221528 -0.030000 -0.106963
+v -0.218915 -0.030000 -0.115773
+v -0.216000 -0.030000 -0.123937
+v -0.212785 -0.030000 -0.131458
+v -0.209271 -0.030000 -0.138337
+v -0.205266 -0.030000 -0.144620
+v -0.200750 -0.030000 -0.150350
+v -0.195723 -0.030000 -0.155529
+v -0.190184 -0.030000 -0.160157
+v -0.184134 -0.030000 -0.164237
+v -0.177573 -0.030000 -0.167769
+v -0.170501 -0.030000 -0.170754
+v -0.162917 -0.030000 -0.173194
+v -0.154823 -0.030000 -0.175090
+v -0.146217 -0.030000 -0.176442
+v -0.137100 -0.030000 -0.177253
+v -0.127471 -0.030000 -0.177523
+v -0.117843 -0.030000 -0.177253
+v -0.108727 -0.030000 -0.176442
+v -0.100125 -0.030000 -0.175090
+v -0.092037 -0.030000 -0.173194
+v -0.084466 -0.030000 -0.170754
+v -0.077411 -0.030000 -0.167769
+v -0.070875 -0.030000 -0.164237
+v -0.064859 -0.030000 -0.160157
+v -0.059363 -0.030000 -0.155529
+v -0.054389 -0.030000 -0.150350
+v -0.049939 -0.030000 -0.144620
+v -0.046012 -0.030000 -0.138337
+v 0.500000 -0.030000 -0.271909
+v 0.500000 0.030000 -0.271909
+v 0.500000 -0.030000 -0.234087
+v 0.500000 0.030000 -0.234087
+v 0.500000 -0.030000 0.229669
+v 0.500000 0.030000 0.229669
+v 0.361282 -0.030000 0.368353
+v 0.361282 0.030000 0.368353
+v -0.369121 -0.030000 0.368353
+v -0.369121 0.030000 0.368353
+v -0.403885 -0.030000 0.368353
+v -0.403885 0.030000 0.368353
+v -0.500000 -0.030000 0.368353
+v -0.500000 0.030000 0.368353
+v -0.500000 -0.030000 0.272263
+v -0.500000 0.030000 0.272263
+v -0.500000 -0.030000 0.234440
+v -0.500000 0.030000 0.234440
+v -0.500000 -0.030000 -0.229316
+v -0.500000 0.030000 -0.229316
+v -0.361282 -0.030000 -0.368000
+v -0.361282 0.030000 -0.368000
+v 0.369121 -0.030000 -0.368000
+v 0.369121 0.030000 -0.368000
+v 0.403886 -0.030000 -0.368000
+v 0.403886 0.030000 -0.368000
+v 0.500000 -0.030000 -0.368000
+v 0.500000 0.030000 -0.368000
+v -0.014123 -0.030000 0.177038
+v -0.014123 0.030000 0.177038
+v -0.008432 -0.030000 0.172481
+v -0.008432 0.030000 0.172481
+v -0.003036 -0.030000 0.167611
+v -0.003036 0.030000 0.167611
+v 0.002070 -0.030000 0.162429
+v 0.002070 0.030000 0.162429
+v 0.006887 -0.030000 0.156934
+v 0.006887 0.030000 0.156934
+v 0.011418 -0.030000 0.151127
+v 0.011418 0.030000 0.151127
+v 0.015664 -0.030000 0.145008
+v 0.015664 0.030000 0.145008
+v 0.019629 -0.030000 0.138577
+v 0.019629 0.030000 0.138577
+v 0.023315 -0.030000 0.131833
+v 0.023315 0.030000 0.131833
+v 0.026724 -0.030000 0.124776
+v 0.026724 0.030000 0.124776
+v 0.029858 -0.030000 0.117408
+v 0.029858 0.030000 0.117408
+v 0.032720 -0.030000 0.109727
+v 0.032720 0.030000 0.109727
+v 0.035255 -0.030000 0.101769
+v 0.035255 0.030000 0.101769
+v 0.037575 -0.030000 0.093399
+v 0.037575 0.030000 0.093399
+v 0.039680 -0.030000 0.084618
+v 0.039680 0.030000 0.084618
+v 0.041569 -0.030000 0.075425
+v 0.041569 0.030000 0.075425
+v 0.043240 -0.030000 0.065820
+v 0.043240 0.030000 0.065820
+v 0.044692 -0.030000 0.055804
+v 0.044692 0.030000 0.055804
+v 0.045923 -0.030000 0.045375
+v 0.045923 0.030000 0.045375
+v 0.046934 -0.030000 0.034535
+v 0.046934 0.030000 0.034535
+v 0.047722 -0.030000 0.023284
+v 0.047722 0.030000 0.023284
+v 0.048286 -0.030000 0.011620
+v 0.048286 0.030000 0.011620
+v 0.048626 -0.030000 -0.000455
+v 0.048626 0.030000 -0.000455
+v 0.048739 -0.030000 -0.012942
+v 0.048739 0.030000 -0.012942
+v 0.048469 -0.030000 -0.031775
+v 0.048469 0.030000 -0.031775
+v 0.047658 -0.030000 -0.049771
+v 0.047658 0.030000 -0.049771
+v 0.046305 -0.030000 -0.066929
+v 0.046305 0.030000 -0.066929
+v 0.044409 -0.030000 -0.083249
+v 0.044409 0.030000 -0.083249
+v 0.041969 -0.030000 -0.098732
+v 0.041969 0.030000 -0.098732
+v 0.038983 -0.030000 -0.113377
+v 0.038983 0.030000 -0.113377
+v 0.035450 -0.030000 -0.127184
+v 0.035450 0.030000 -0.127184
+v 0.031369 -0.030000 -0.140154
+v 0.031369 0.030000 -0.140154
+v 0.026739 -0.030000 -0.152286
+v 0.026739 0.030000 -0.152286
+v 0.021559 -0.030000 -0.163580
+v 0.021559 0.030000 -0.163580
+v 0.015828 -0.030000 -0.174037
+v 0.015828 0.030000 -0.174037
+v 0.009543 -0.030000 -0.183656
+v 0.009543 0.030000 -0.183656
+v 0.002656 -0.030000 -0.192551
+v 0.002656 0.030000 -0.192551
+v -0.005054 -0.030000 -0.200667
+v -0.005054 0.030000 -0.200667
+v -0.013585 -0.030000 -0.208004
+v -0.013585 0.030000 -0.208004
+v -0.022937 -0.030000 -0.214563
+v -0.022937 0.030000 -0.214563
+v -0.033107 -0.030000 -0.220347
+v -0.033107 0.030000 -0.220347
+v -0.044095 -0.030000 -0.225355
+v -0.044095 0.030000 -0.225355
+v -0.055900 -0.030000 -0.229590
+v -0.055900 0.030000 -0.229590
+v -0.068520 -0.030000 -0.233052
+v -0.068520 0.030000 -0.233052
+v -0.081954 -0.030000 -0.235742
+v -0.081954 0.030000 -0.235742
+v -0.096201 -0.030000 -0.237663
+v -0.096201 0.030000 -0.237663
+v -0.111260 -0.030000 -0.238814
+v -0.111260 0.030000 -0.238814
+v -0.127130 -0.030000 -0.239198
+v -0.127130 0.030000 -0.239198
+v -0.143000 -0.030000 -0.238808
+v -0.143000 0.030000 -0.238808
+v -0.158061 -0.030000 -0.237638
+v -0.158061 0.030000 -0.237638
+v -0.172312 -0.030000 -0.235689
+v -0.172312 0.030000 -0.235689
+v -0.185753 -0.030000 -0.232963
+v -0.185753 0.030000 -0.232963
+v -0.198385 -0.030000 -0.229461
+v -0.198385 0.030000 -0.229461
+v -0.210208 -0.030000 -0.225185
+v -0.210208 0.030000 -0.225185
+v -0.221221 -0.030000 -0.220134
+v -0.221221 0.030000 -0.220134
+v -0.231425 -0.030000 -0.214311
+v -0.231425 0.030000 -0.214311
+v -0.240819 -0.030000 -0.207716
+v -0.240819 0.030000 -0.207716
+v -0.249404 -0.030000 -0.200351
+v -0.249404 0.030000 -0.200351
+v -0.257179 -0.030000 -0.192217
+v -0.257179 0.030000 -0.192217
+v -0.264144 -0.030000 -0.183315
+v -0.264144 0.030000 -0.183315
+v -0.270435 -0.030000 -0.173618
+v -0.270435 0.030000 -0.173618
+v -0.276186 -0.030000 -0.163098
+v -0.276186 0.030000 -0.163098
+v -0.281394 -0.030000 -0.151754
+v -0.281394 0.030000 -0.151754
+v -0.286059 -0.030000 -0.139586
+v -0.286059 0.030000 -0.139586
+v -0.290179 -0.030000 -0.126595
+v -0.290179 0.030000 -0.126595
+v -0.293754 -0.030000 -0.112781
+v -0.293754 0.030000 -0.112781
+v -0.296782 -0.030000 -0.098143
+v -0.296782 0.030000 -0.098143
+v -0.299263 -0.030000 -0.082682
+v -0.299263 0.030000 -0.082682
+v -0.301194 -0.030000 -0.066397
+v -0.301194 0.030000 -0.066397
+v -0.302575 -0.030000 -0.049288
+v -0.302575 0.030000 -0.049288
+v -0.303404 -0.030000 -0.031357
+v -0.303404 0.030000 -0.031357
+v -0.303681 -0.030000 -0.012601
+v -0.303681 0.030000 -0.012601
+v -0.303411 -0.030000 0.006061
+v -0.303411 0.030000 0.006061
+v -0.302602 -0.030000 0.023884
+v -0.302602 0.030000 0.023884
+v -0.301253 -0.030000 0.040864
+v -0.301253 0.030000 0.040864
+v -0.299364 -0.030000 0.056999
+v -0.299364 0.030000 0.056999
+v -0.296935 -0.030000 0.072288
+v -0.296935 0.030000 0.072288
+v -0.293967 -0.030000 0.086726
+v -0.293967 0.030000 0.086726
+v -0.290460 -0.030000 0.100313
+v -0.290460 0.030000 0.100313
+v -0.286412 -0.030000 0.113046
+v -0.286412 0.030000 0.113046
+v -0.281825 -0.030000 0.124922
+v -0.281825 0.030000 0.124922
+v -0.276698 -0.030000 0.135939
+v -0.276698 0.030000 0.135939
+v -0.271032 -0.030000 0.146095
+v -0.271032 0.030000 0.146095
+v -0.264826 -0.030000 0.155387
+v -0.264826 0.030000 0.155387
+v -0.257932 -0.030000 0.163877
+v -0.257932 0.030000 0.163877
+v -0.250200 -0.030000 0.171629
+v -0.250200 0.030000 0.171629
+v -0.241634 -0.030000 0.178643
+v -0.241634 0.030000 0.178643
+v -0.232233 -0.030000 0.184918
+v -0.232233 0.030000 0.184918
+v -0.221998 -0.030000 0.190455
+v -0.221998 0.030000 0.190455
+v -0.210932 -0.030000 0.195254
+v -0.210932 0.030000 0.195254
+v -0.199035 -0.030000 0.199315
+v -0.199035 0.030000 0.199315
+v -0.186309 -0.030000 0.202637
+v -0.186309 0.030000 0.202637
+v -0.172754 -0.030000 0.205221
+v -0.172754 0.030000 0.205221
+v -0.158371 -0.030000 0.207067
+v -0.158371 0.030000 0.207067
+v -0.143163 -0.030000 0.208174
+v -0.143163 0.030000 0.208174
+v -0.127130 -0.030000 0.208543
+v -0.127130 0.030000 0.208543
+v -0.122805 -0.030000 0.208515
+v -0.122805 0.030000 0.208515
+v -0.118691 -0.030000 0.208431
+v -0.118691 0.030000 0.208431
+v -0.114786 -0.030000 0.208293
+v -0.114786 0.030000 0.208293
+v -0.111086 -0.030000 0.208101
+v -0.111086 0.030000 0.208101
+v -0.107590 -0.030000 0.207858
+v -0.107590 0.030000 0.207858
+v -0.104294 -0.030000 0.207563
+v -0.104294 0.030000 0.207563
+v -0.101198 -0.030000 0.207219
+v -0.101198 0.030000 0.207219
+v -0.098298 -0.030000 0.206827
+v -0.098298 0.030000 0.206827
+v -0.095593 -0.030000 0.206387
+v -0.095593 0.030000 0.206387
+v -0.093079 -0.030000 0.205901
+v -0.093079 0.030000 0.205901
+v -0.090754 -0.030000 0.205370
+v -0.090754 0.030000 0.205370
+v -0.088616 -0.030000 0.204795
+v -0.088616 0.030000 0.204795
+v -0.032379 -0.030000 0.297137
+v -0.032379 0.030000 0.297137
+v 0.032720 -0.030000 0.266811
+v 0.032720 0.030000 0.266811
+v 0.027981 -0.030000 0.259139
+v 0.027981 0.030000 0.259139
+v 0.022692 -0.030000 0.250576
+v 0.022692 0.030000 0.250576
+v 0.017036 -0.030000 0.241420
+v 0.017036 0.030000 0.241420
+v 0.011197 -0.030000 0.231966
+v 0.011197 0.030000 0.231966
+v 0.005358 -0.030000 0.222513
+v 0.005358 0.030000 0.222513
+v -0.000298 -0.030000 0.213356
+v -0.000298 0.030000 0.213356
+v -0.005587 -0.030000 0.204794
+v -0.005587 0.030000 0.204794
+v -0.010326 -0.030000 0.197122
+v -0.010326 0.030000 0.197122
+v -0.014331 -0.030000 0.190638
+v -0.014331 0.030000 0.190638
+v -0.017419 -0.030000 0.185639
+v -0.017419 0.030000 0.185639
+v -0.019406 -0.030000 0.182422
+v -0.019406 0.030000 0.182422
+v -0.020109 -0.030000 0.181283
+v -0.020109 0.030000 0.181283
+v 0.291411 -0.030000 0.137327
+v 0.291411 0.030000 0.137327
+v 0.286764 -0.030000 0.137511
+v 0.286764 0.030000 0.137511
+v 0.281577 -0.030000 0.137715
+v 0.281577 0.030000 0.137715
+v 0.276031 -0.030000 0.137934
+v 0.276031 0.030000 0.137934
+v 0.270305 -0.030000 0.138160
+v 0.270305 0.030000 0.138160
+v 0.264578 -0.030000 0.138386
+v 0.264578 0.030000 0.138386
+v 0.259032 -0.030000 0.138605
+v 0.259032 0.030000 0.138605
+v 0.253845 -0.030000 0.138810
+v 0.253845 0.030000 0.138810
+v 0.249198 -0.030000 0.138993
+v 0.249198 0.030000 0.138993
+v 0.245271 -0.030000 0.139148
+v 0.245271 0.030000 0.139148
+v 0.242243 -0.030000 0.139267
+v 0.242243 0.030000 0.139267
+v 0.240294 -0.030000 0.139344
+v 0.240294 0.030000 0.139344
+v 0.239605 -0.030000 0.139372
+v 0.239605 0.030000 0.139372
+v 0.235884 -0.030000 0.139286
+v 0.235884 0.030000 0.139286
+v 0.232394 -0.030000 0.139029
+v 0.232394 0.030000 0.139029
+v 0.229135 -0.030000 0.138600
+v 0.229135 0.030000 0.138600
+v 0.226110 -0.030000 0.137996
+v 0.226110 0.030000 0.137996
+v 0.223322 -0.030000 0.137217
+v 0.223322 0.030000 0.137217
+v 0.220774 -0.030000 0.136262
+v 0.220774 0.030000 0.136262
+v 0.218466 -0.030000 0.135130
+v 0.218466 0.030000 0.135130
+v 0.216403 -0.030000 0.133819
+v 0.216403 0.030000 0.133819
+v 0.214585 -0.030000 0.132328
+v 0.214585 0.030000 0.132328
+v 0.213017 -0.030000 0.130656
+v 0.213017 0.030000 0.130656
+v 0.211699 -0.030000 0.128802
+v 0.211699 0.030000 0.128802
+v 0.210634 -0.030000 0.126764
+v 0.210634 0.030000 0.126764
+v 0.209732 -0.030000 0.124535
+v 0.209732 0.030000 0.124535
+v 0.208903 -0.030000 0.121937
+v 0.208903 0.030000 0.121937
+v 0.208147 -0.030000 0.118969
+v 0.208147 0.030000 0.118969
+v 0.207465 -0.030000 0.115633
+v 0.207465 0.030000 0.115633
+v 0.206860 -0.030000 0.111927
+v 0.206860 0.030000 0.111927
+v 0.206331 -0.030000 0.107853
+v 0.206331 0.030000 0.107853
+v 0.205880 -0.030000 0.103409
+v 0.205880 0.030000 0.103409
+v 0.205509 -0.030000 0.098596
+v 0.205509 0.030000 0.098596
+v 0.205218 -0.030000 0.093413
+v 0.205218 0.030000 0.093413
+v 0.205009 -0.030000 0.087862
+v 0.205009 0.030000 0.087862
+v 0.204882 -0.030000 0.081942
+v 0.204882 0.030000 0.081942
+v 0.204840 -0.030000 0.075652
+v 0.204840 0.030000 0.075652
+v 0.204840 -0.030000 -0.063713
+v 0.204840 0.030000 -0.063713
+v 0.292093 -0.030000 -0.063713
+v 0.292093 0.030000 -0.063713
+v 0.292093 -0.030000 -0.122662
+v 0.292093 0.030000 -0.122662
+v 0.204840 -0.030000 -0.122662
+v 0.204840 0.030000 -0.122662
+v 0.204840 -0.030000 -0.214664
+v 0.204840 0.030000 -0.214664
+v 0.136333 -0.030000 -0.214664
+v 0.136333 0.030000 -0.214664
+v 0.136333 -0.030000 -0.122662
+v 0.136333 0.030000 -0.122662
+v 0.087935 -0.030000 -0.122662
+v 0.087935 0.030000 -0.122662
+v 0.087935 -0.030000 -0.064054
+v 0.087935 0.030000 -0.064054
+v 0.136333 -0.030000 -0.064054
+v 0.136333 0.030000 -0.064054
+v 0.136333 -0.030000 -0.050850
+v 0.136333 0.030000 -0.050850
+v 0.136333 -0.030000 -0.036113
+v 0.136333 0.030000 -0.036113
+v 0.136333 -0.030000 -0.020353
+v 0.136333 0.030000 -0.020353
+v 0.136333 -0.030000 -0.004083
+v 0.136333 0.030000 -0.004083
+v 0.136333 -0.030000 0.012188
+v 0.136333 0.030000 0.012188
+v 0.136333 -0.030000 0.027947
+v 0.136333 0.030000 0.027947
+v 0.136333 -0.030000 0.042685
+v 0.136333 0.030000 0.042685
+v 0.136333 -0.030000 0.055889
+v 0.136333 0.030000 0.055889
+v 0.136333 -0.030000 0.067048
+v 0.136333 0.030000 0.067048
+v 0.136333 -0.030000 0.075652
+v 0.136333 0.030000 0.075652
+v 0.136333 -0.030000 0.081189
+v 0.136333 0.030000 0.081189
+v 0.136333 -0.030000 0.083148
+v 0.136333 0.030000 0.083148
+v 0.136475 -0.030000 0.094258
+v 0.136475 0.030000 0.094258
+v 0.136899 -0.030000 0.104757
+v 0.136899 0.030000 0.104757
+v 0.137605 -0.030000 0.114646
+v 0.137605 0.030000 0.114646
+v 0.138592 -0.030000 0.123924
+v 0.138592 0.030000 0.123924
+v 0.139858 -0.030000 0.132592
+v 0.139858 0.030000 0.132592
+v 0.141403 -0.030000 0.140649
+v 0.141403 0.030000 0.140649
+v 0.143224 -0.030000 0.148096
+v 0.143224 0.030000 0.148096
+v 0.145321 -0.030000 0.154932
+v 0.145321 0.030000 0.154932
+v 0.147692 -0.030000 0.161158
+v 0.147692 0.030000 0.161158
+v 0.150337 -0.030000 0.166773
+v 0.150337 0.030000 0.166773
+v 0.153254 -0.030000 0.171778
+v 0.153254 0.030000 0.171778
+v 0.156442 -0.030000 0.176172
+v 0.156442 0.030000 0.176172
+v 0.159999 -0.030000 0.180091
+v 0.159999 0.030000 0.180091
+v 0.164025 -0.030000 0.183669
+v 0.164025 0.030000 0.183669
+v 0.168520 -0.030000 0.186906
+v 0.168520 0.030000 0.186906
+v 0.173483 -0.030000 0.189802
+v 0.173483 0.030000 0.189802
+v 0.178915 -0.030000 0.192358
+v 0.178915 0.030000 0.192358
+v 0.184816 -0.030000 0.194573
+v 0.184816 0.030000 0.194573
+v 0.191185 -0.030000 0.196447
+v 0.191185 0.030000 0.196447
+v 0.198023 -0.030000 0.197980
+v 0.198023 0.030000 0.197980
+v 0.205330 -0.030000 0.199173
+v 0.205330 0.030000 0.199173
+v 0.213105 -0.030000 0.200024
+v 0.213105 0.030000 0.200024
+v 0.221349 -0.030000 0.200536
+v 0.221349 0.030000 0.200536
+v 0.230061 -0.030000 0.200706
+v 0.230061 0.030000 0.200706
+v 0.233945 -0.030000 0.200649
+v 0.233945 0.030000 0.200649
+v 0.238099 -0.030000 0.200479
+v 0.238099 0.030000 0.200479
+v 0.242523 -0.030000 0.200195
+v 0.242523 0.030000 0.200195
+v 0.247217 -0.030000 0.199797
+v 0.247217 0.030000 0.199797
+v 0.252180 -0.030000 0.199286
+v 0.252180 0.030000 0.199286
+v 0.257413 -0.030000 0.198662
+v 0.257413 0.030000 0.198662
+v 0.262916 -0.030000 0.197923
+v 0.262916 0.030000 0.197923
+v 0.268689 -0.030000 0.197071
+v 0.268689 0.030000 0.197071
+v 0.274732 -0.030000 0.196106
+v 0.274732 0.030000 0.196106
+v 0.281044 -0.030000 0.195027
+v 0.281044 0.030000 0.195027
+v 0.287626 -0.030000 0.193834
+v 0.287626 0.030000 0.193834
+v 0.294479 -0.030000 0.192528
+v 0.294479 0.030000 0.192528
+v -0.042504 -0.030000 -0.131451
+v -0.042504 0.030000 -0.131451
+v -0.039308 -0.030000 -0.123910
+v -0.039308 0.030000 -0.123910
+v -0.036421 -0.030000 -0.115714
+v -0.036421 0.030000 -0.115714
+v -0.033843 -0.030000 -0.106862
+v -0.033843 0.030000 -0.106862
+v -0.031573 -0.030000 -0.097352
+v -0.031573 0.030000 -0.097352
+v -0.029610 -0.030000 -0.087182
+v -0.029610 0.030000 -0.087182
+v -0.027952 -0.030000 -0.076353
+v -0.027952 0.030000 -0.076353
+v -0.026597 -0.030000 -0.064862
+v -0.026597 0.030000 -0.064862
+v -0.025546 -0.030000 -0.052708
+v -0.025546 0.030000 -0.052708
+v -0.024797 -0.030000 -0.039891
+v -0.024797 0.030000 -0.039891
+v -0.024348 -0.030000 -0.026409
+v -0.024348 0.030000 -0.026409
+v -0.024199 -0.030000 -0.012261
+v -0.024199 0.030000 -0.012261
+v -0.024348 -0.030000 0.001795
+v -0.024348 0.030000 0.001795
+v -0.024794 -0.030000 0.015166
+v -0.024794 0.030000 0.015166
+v -0.025536 -0.030000 0.027852
+v -0.025536 0.030000 0.027852
+v -0.026572 -0.030000 0.039848
+v -0.026572 0.030000 0.039848
+v -0.027902 -0.030000 0.051154
+v -0.027902 0.030000 0.051154
+v -0.029525 -0.030000 0.061767
+v -0.029525 0.030000 0.061767
+v -0.031438 -0.030000 0.071683
+v -0.031438 0.030000 0.071683
+v -0.033641 -0.030000 0.080902
+v -0.033641 0.030000 0.080902
+v -0.036133 -0.030000 0.089420
+v -0.036133 0.030000 0.089420
+v -0.038913 -0.030000 0.097236
+v -0.038913 0.030000 0.097236
+v -0.041979 -0.030000 0.104346
+v -0.041979 0.030000 0.104346
+v -0.045331 -0.030000 0.110749
+v -0.045331 0.030000 0.110749
+v -0.049179 -0.030000 0.116548
+v -0.049179 0.030000 0.116548
+v -0.053569 -0.030000 0.121850
+v -0.053569 0.030000 0.121850
+v -0.058501 -0.030000 0.126652
+v -0.058501 0.030000 0.126652
+v -0.063975 -0.030000 0.130954
+v -0.063975 0.030000 0.130954
+v -0.069995 -0.030000 0.134754
+v -0.069995 0.030000 0.134754
+v -0.076559 -0.030000 0.138051
+v -0.076559 0.030000 0.138051
+v -0.083671 -0.030000 0.140844
+v -0.083671 0.030000 0.140844
+v -0.091330 -0.030000 0.143132
+v -0.091330 0.030000 0.143132
+v -0.099539 -0.030000 0.144914
+v -0.099539 0.030000 0.144914
+v -0.108298 -0.030000 0.146188
+v -0.108298 0.030000 0.146188
+v -0.117608 -0.030000 0.146953
+v -0.117608 0.030000 0.146953
+v -0.127471 -0.030000 0.147209
+v -0.127471 0.030000 0.147209
+v -0.137341 -0.030000 0.146947
+v -0.137341 0.030000 0.146947
+v -0.146670 -0.030000 0.146161
+v -0.146670 0.030000 0.146161
+v -0.155456 -0.030000 0.144855
+v -0.155456 0.030000 0.144855
+v -0.163700 -0.030000 0.143031
+v -0.163700 0.030000 0.143031
+v -0.171399 -0.030000 0.140692
+v -0.171399 0.030000 0.140692
+v -0.178553 -0.030000 0.137838
+v -0.178553 0.030000 0.137838
+v -0.185160 -0.030000 0.134474
+v -0.185160 0.030000 0.134474
+v -0.191219 -0.030000 0.130601
+v -0.191219 0.030000 0.130601
+v -0.196729 -0.030000 0.126221
+v -0.196729 0.030000 0.126221
+v -0.201689 -0.030000 0.121337
+v -0.201689 0.030000 0.121337
+v -0.206097 -0.030000 0.115952
+v -0.206097 0.030000 0.115952
+v -0.209952 -0.030000 0.110067
+v -0.209952 0.030000 0.110067
+v -0.213382 -0.030000 0.103587
+v -0.213382 0.030000 0.103587
+v -0.216513 -0.030000 0.096412
+v -0.216513 0.030000 0.096412
+v -0.219346 -0.030000 0.088547
+v -0.219346 0.030000 0.088547
+v -0.221881 -0.030000 0.079993
+v -0.221881 0.030000 0.079993
+v -0.224118 -0.030000 0.070753
+v -0.224118 0.030000 0.070753
+v -0.226057 -0.030000 0.060830
+v -0.226057 0.030000 0.060830
+v -0.227697 -0.030000 0.050224
+v -0.227697 0.030000 0.050224
+v -0.229039 -0.030000 0.038940
+v -0.229039 0.030000 0.038940
+v -0.230083 -0.030000 0.026978
+v -0.230083 0.030000 0.026978
+v -0.230828 -0.030000 0.014343
+v -0.230828 0.030000 0.014343
+v -0.231276 -0.030000 0.001035
+v -0.231276 0.030000 0.001035
+v -0.231425 -0.030000 -0.012942
+v -0.231425 0.030000 -0.012942
+v -0.231269 -0.030000 -0.027005
+v -0.231269 0.030000 -0.027005
+v -0.230801 -0.030000 -0.040404
+v -0.230801 0.030000 -0.040404
+v -0.230024 -0.030000 -0.053140
+v -0.230024 0.030000 -0.053140
+v -0.228938 -0.030000 -0.065215
+v -0.228938 0.030000 -0.065215
+v -0.227544 -0.030000 -0.076633
+v -0.227544 0.030000 -0.076633
+v -0.225844 -0.030000 -0.087395
+v -0.225844 0.030000 -0.087395
+v -0.223838 -0.030000 -0.097504
+v -0.223838 0.030000 -0.097504
+v -0.221528 -0.030000 -0.106963
+v -0.221528 0.030000 -0.106963
+v -0.218915 -0.030000 -0.115773
+v -0.218915 0.030000 -0.115773
+v -0.216000 -0.030000 -0.123937
+v -0.216000 0.030000 -0.123937
+v -0.212785 -0.030000 -0.131458
+v -0.212785 0.030000 -0.131458
+v -0.209271 -0.030000 -0.138337
+v -0.209271 0.030000 -0.138337
+v -0.205266 -0.030000 -0.144620
+v -0.205266 0.030000 -0.144620
+v -0.200750 -0.030000 -0.150350
+v -0.200750 0.030000 -0.150350
+v -0.195723 -0.030000 -0.155529
+v -0.195723 0.030000 -0.155529
+v -0.190184 -0.030000 -0.160157
+v -0.190184 0.030000 -0.160157
+v -0.184134 -0.030000 -0.164237
+v -0.184134 0.030000 -0.164237
+v -0.177573 -0.030000 -0.167769
+v -0.177573 0.030000 -0.167769
+v -0.170501 -0.030000 -0.170754
+v -0.170501 0.030000 -0.170754
+v -0.162917 -0.030000 -0.173194
+v -0.162917 0.030000 -0.173194
+v -0.154823 -0.030000 -0.175090
+v -0.154823 0.030000 -0.175090
+v -0.146217 -0.030000 -0.176442
+v -0.146217 0.030000 -0.176442
+v -0.137100 -0.030000 -0.177253
+v -0.137100 0.030000 -0.177253
+v -0.127471 -0.030000 -0.177523
+v -0.127471 0.030000 -0.177523
+v -0.117843 -0.030000 -0.177253
+v -0.117843 0.030000 -0.177253
+v -0.108727 -0.030000 -0.176442
+v -0.108727 0.030000 -0.176442
+v -0.100125 -0.030000 -0.175090
+v -0.100125 0.030000 -0.175090
+v -0.092037 -0.030000 -0.173194
+v -0.092037 0.030000 -0.173194
+v -0.084466 -0.030000 -0.170754
+v -0.084466 0.030000 -0.170754
+v -0.077411 -0.030000 -0.167769
+v -0.077411 0.030000 -0.167769
+v -0.070875 -0.030000 -0.164237
+v -0.070875 0.030000 -0.164237
+v -0.064859 -0.030000 -0.160157
+v -0.064859 0.030000 -0.160157
+v -0.059363 -0.030000 -0.155529
+v -0.059363 0.030000 -0.155529
+v -0.054389 -0.030000 -0.150350
+v -0.054389 0.030000 -0.150350
+v -0.049939 -0.030000 -0.144620
+v -0.049939 0.030000 -0.144620
+v -0.046012 -0.030000 -0.138337
+v -0.046012 0.030000 -0.138337
+vn 0.0000 1.0000 0.0000
+vn 0.0000 0.0000 1.0000
+vn 0.0000 0.0000 -1.0000
+vn 0.0000 -1.0000 0.0000
+vn 0.0000 -1.0000 -0.0001
+vn 0.0000 -1.0000 0.0001
+vn 1.0000 0.0000 0.0000
+vn 0.9238 0.0000 0.3827
+vn 0.3826 0.0000 0.9239
+vn -0.7071 0.0000 0.7071
+vn -1.0000 0.0000 0.0000
+vn -0.9238 0.0000 -0.3827
+vn -0.3826 0.0000 -0.9239
+vn 0.7071 0.0000 -0.7071
+vn -0.6478 0.0000 -0.7618
+vn -0.6020 0.0000 -0.7985
+vn -0.6914 0.0000 -0.7224
+vn -0.7324 0.0000 -0.6808
+vn -0.7705 0.0000 -0.6374
+vn -0.8053 0.0000 -0.5929
+vn -0.8367 0.0000 -0.5477
+vn -0.8647 0.0000 -0.5023
+vn -0.8367 0.0000 -0.5476
+vn -0.8892 0.0000 -0.4574
+vn -0.9106 0.0000 -0.4133
+vn -0.9289 0.0000 -0.3704
+vn -0.9452 0.0000 -0.3264
+vn -0.9584 0.0000 -0.2854
+vn -0.9682 0.0000 -0.2502
+vn -0.9761 0.0000 -0.2172
+vn -0.9825 0.0000 -0.1863
+vn -0.9875 0.0000 -0.1574
+vn -0.9915 0.0000 -0.1304
+vn -0.9944 0.0000 -0.1050
+vn -0.9967 0.0000 -0.0813
+vn -0.9982 0.0000 -0.0591
+vn -0.9993 0.0000 -0.0382
+vn -0.9998 0.0000 -0.0186
+vn -1.0000 0.0000 0.0026
+vn -0.9995 0.0000 0.0297
+vn -0.9981 0.0000 0.0618
+vn -0.9953 0.0000 0.0970
+vn -0.9908 0.0000 0.1356
+vn -0.9840 0.0000 0.1778
+vn -0.9746 0.0000 0.2239
+vn -0.9617 0.0000 0.2741
+vn -0.9445 0.0000 0.3285
+vn -0.9221 0.0000 0.3869
+vn -0.8935 0.0000 0.4490
+vn -0.8577 0.0000 0.5142
+vn -0.8146 0.0000 0.5800
+vn -0.7588 0.0000 0.6513
+vn -0.6894 0.0000 0.7244
+vn -0.6139 0.0000 0.7894
+vn -0.5349 0.0000 0.8449
+vn -0.4550 0.0000 0.8905
+vn -0.3765 0.0000 0.9264
+vn -0.3013 0.0000 0.9535
+vn -0.2306 0.0000 0.9730
+vn -0.1650 0.0000 0.9863
+vn -0.1050 0.0000 0.9945
+vn -0.0502 0.0000 0.9987
+vn 0.0002 0.0000 1.0000
+vn 0.0510 0.0000 0.9987
+vn 0.1065 0.0000 0.9943
+vn 0.1672 0.0000 0.9859
+vn 0.2331 0.0000 0.9724
+vn 0.3039 0.0000 0.9527
+vn 0.3788 0.0000 0.9254
+vn 0.4567 0.0000 0.8896
+vn 0.5357 0.0000 0.8444
+vn 0.6135 0.0000 0.7896
+vn 0.6878 0.0000 0.7259
+vn 0.7561 0.0000 0.6544
+vn 0.8140 0.0000 0.5808
+vn 0.8588 0.0000 0.5123
+vn 0.8937 0.0000 0.4487
+vn 0.9217 0.0000 0.3878
+vn 0.9438 0.0000 0.3303
+vn 0.9610 0.0000 0.2765
+vn 0.9740 0.0000 0.2266
+vn 0.9836 0.0000 0.1805
+vn 0.9904 0.0000 0.1381
+vn 0.9951 0.0000 0.0991
+vn 0.9980 0.0000 0.0633
+vn 0.9995 0.0000 0.0305
+vn 1.0000 0.0000 0.0001
+vn 0.9995 0.0000 -0.0299
+vn 0.9980 0.0000 -0.0623
+vn 0.9952 0.0000 -0.0978
+vn 0.9906 0.0000 -0.1366
+vn 0.9838 0.0000 -0.1791
+vn 0.9742 0.0000 -0.2257
+vn 0.9610 0.0000 -0.2766
+vn 0.9434 0.0000 -0.3318
+vn 0.9203 0.0000 -0.3913
+vn 0.8905 0.0000 -0.4548
+vn 0.8531 0.0000 -0.5217
+vn 0.8048 0.0000 -0.5935
+vn 0.7431 0.0000 -0.6691
+vn 0.6716 0.0000 -0.7409
+vn 0.5950 0.0000 -0.8037
+vn 0.5161 0.0000 -0.8565
+vn 0.4372 0.0000 -0.8993
+vn 0.3607 0.0000 -0.9326
+vn 0.2880 0.0000 -0.9576
+vn 0.2200 0.0000 -0.9755
+vn 0.1573 0.0000 -0.9875
+vn 0.1000 0.0000 -0.9950
+vn 0.0478 0.0000 -0.9988
+vn 0.0082 0.0000 -0.9999
+vn -0.0134 0.0000 -0.9999
+vn -0.0279 0.0000 -0.9996
+vn -0.0435 0.0000 -0.9990
+vn -0.0606 0.0000 -0.9981
+vn -0.0792 0.0000 -0.9968
+vn -0.0997 0.0000 -0.9950
+vn -0.1223 0.0000 -0.9925
+vn -0.1473 0.0000 -0.9891
+vn -0.1752 0.0000 -0.9845
+vn -0.2063 0.0000 -0.9785
+vn -0.1751 0.0000 -0.9845
+vn -0.2412 0.0000 -0.9705
+vn 0.3714 0.0000 -0.9284
+vn 0.2897 0.0000 -0.9571
+vn -0.9580 0.0000 -0.2867
+vn -0.8508 0.0000 0.5255
+vn -0.9800 0.0000 -0.1990
+vn 0.0394 0.0000 0.9992
+vn -0.6727 0.0000 0.7399
+vn 0.0395 0.0000 0.9992
+vn 0.0083 0.0000 0.9999
+vn -0.0482 0.0000 0.9988
+vn 0.0082 0.0000 0.9999
+vn -0.1021 0.0000 0.9948
+vn -0.1633 0.0000 0.9866
+vn -0.2325 0.0000 0.9726
+vn -0.3102 0.0000 0.9507
+vn -0.3962 0.0000 0.9181
+vn -0.4892 0.0000 0.8722
+vn -0.5863 0.0000 0.8101
+vn -0.6832 0.0000 0.7302
+vn -0.7739 0.0000 0.6333
+vn -0.8527 0.0000 0.5224
+vn -0.9077 0.0000 0.4195
+vn -0.9405 0.0000 0.3398
+vn -0.9612 0.0000 0.2756
+vn -0.9747 0.0000 0.2235
+vn -0.9835 0.0000 0.1807
+vn -0.9894 0.0000 0.1450
+vn -0.9934 0.0000 0.1148
+vn -0.9960 0.0000 0.0889
+vn -0.9978 0.0000 0.0665
+vn -0.9989 0.0000 0.0468
+vn -0.9995 0.0000 0.0295
+vn -0.9999 0.0000 0.0140
+vn -1.0000 0.0000 0.0034
+vn -0.7071 0.0000 -0.7071
+vn 0.7071 0.0000 0.7071
+vn 1.0000 0.0000 -0.0064
+vn 0.9996 0.0000 -0.0266
+vn 0.9984 0.0000 -0.0558
+vn 0.9961 0.0000 -0.0885
+vn 0.9921 0.0000 -0.1252
+vn 0.9861 0.0000 -0.1664
+vn 0.9771 0.0000 -0.2129
+vn 0.9641 0.0000 -0.2655
+vn 0.9458 0.0000 -0.3248
+vn 0.8852 0.0000 -0.4653
+vn 0.8377 0.0000 -0.5461
+vn 0.7761 0.0000 -0.6306
+vn 0.7033 0.0000 -0.7108
+vn 0.6251 0.0000 -0.7805
+vn 0.5448 0.0000 -0.8385
+vn 0.4653 0.0000 -0.8851
+vn 0.3889 0.0000 -0.9213
+vn 0.3170 0.0000 -0.9484
+vn 0.2506 0.0000 -0.9680
+vn 0.3171 0.0000 -0.9484
+vn 0.1900 0.0000 -0.9817
+vn 0.1350 0.0000 -0.9908
+vn 0.0854 0.0000 -0.9963
+vn 0.0407 0.0000 -0.9991
+vn 0.0024 0.0000 -1.0000
+vn -0.0278 0.0000 -0.9996
+vn -0.0525 0.0000 -0.9986
+vn -0.0742 0.0000 -0.9972
+vn -0.0934 0.0000 -0.9956
+vn -0.1105 0.0000 -0.9939
+vn -0.1257 0.0000 -0.9920
+vn -0.1395 0.0000 -0.9902
+vn -0.1519 0.0000 -0.9884
+vn -0.1631 0.0000 -0.9866
+vn -0.1734 0.0000 -0.9848
+vn -0.1827 0.0000 -0.9832
+vn -0.7879 0.0000 -0.6158
+vn 0.9324 0.0000 -0.3614
+vn 0.9064 0.0000 -0.4223
+vn 0.9520 0.0000 -0.3060
+vn 0.9667 0.0000 -0.2559
+vn 0.9775 0.0000 -0.2109
+vn 0.9854 0.0000 -0.1705
+vn 0.9909 0.0000 -0.1342
+vn 0.9948 0.0000 -0.1016
+vn 0.9974 0.0000 -0.0723
+vn 0.9989 0.0000 -0.0458
+vn 0.9998 0.0000 -0.0219
+vn 0.9998 0.0000 0.0219
+vn 0.9989 0.0000 0.0458
+vn 0.9974 0.0000 0.0722
+vn 0.9948 0.0000 0.1014
+vn 0.9910 0.0000 0.1340
+vn 0.9854 0.0000 0.1703
+vn 0.9775 0.0000 0.2110
+vn 0.9665 0.0000 0.2567
+vn 0.9514 0.0000 0.3081
+vn 0.9307 0.0000 0.3657
+vn 0.9027 0.0000 0.4301
+vn 0.8607 0.0000 0.5090
+vn 0.8028 0.0000 0.5962
+vn 0.7350 0.0000 0.6781
+vn 0.6587 0.0000 0.7524
+vn 0.5766 0.0000 0.8170
+vn 0.4919 0.0000 0.8706
+vn 0.4076 0.0000 0.9131
+vn 0.3262 0.0000 0.9453
+vn 0.2493 0.0000 0.9684
+vn 0.1781 0.0000 0.9840
+vn 0.1130 0.0000 0.9936
+vn 0.0539 0.0000 0.9985
+vn -0.0003 0.0000 1.0000
+vn -0.0552 0.0000 0.9984
+vn -0.1155 0.0000 0.9933
+vn -0.1816 0.0000 0.9834
+vn -0.2536 0.0000 0.9673
+vn -0.1816 0.0000 0.9833
+vn -0.3309 0.0000 0.9436
+vn -0.4125 0.0000 0.9109
+vn -0.4968 0.0000 0.8679
+vn -0.5812 0.0000 0.8137
+vn -0.6629 0.0000 0.7487
+vn -0.7388 0.0000 0.6739
+vn -0.8063 0.0000 0.5915
+vn -0.8611 0.0000 0.5084
+vn -0.9008 0.0000 0.4342
+vn -0.9291 0.0000 0.3696
+vn -0.9502 0.0000 0.3116
+vn -0.9656 0.0000 0.2598
+vn -0.9769 0.0000 0.2135
+vn -0.9850 0.0000 0.1723
+vn -0.9908 0.0000 0.1355
+vn -0.9947 0.0000 0.1025
+vn -0.9973 0.0000 0.0729
+vn -0.9989 0.0000 0.0462
+vn -0.9997 0.0000 0.0221
+vn -1.0000 0.0000 -0.0002
+vn -0.9997 0.0000 -0.0229
+vn -0.9988 0.0000 -0.0479
+vn -0.9972 0.0000 -0.0753
+vn -0.9944 0.0000 -0.1054
+vn -0.9903 0.0000 -0.1386
+vn -0.9845 0.0000 -0.1754
+vn -0.9764 0.0000 -0.2159
+vn -0.9654 0.0000 -0.2608
+vn -0.9506 0.0000 -0.3104
+vn -0.9311 0.0000 -0.3648
+vn -0.9055 0.0000 -0.4243
+vn -0.8679 0.0000 -0.4968
+vn -0.8153 0.0000 -0.5790
+vn -0.7525 0.0000 -0.6586
+vn -0.6803 0.0000 -0.7329
+vn -0.6010 0.0000 -0.7992
+vn -0.5172 0.0000 -0.8559
+vn -0.4319 0.0000 -0.9019
+vn -0.3479 0.0000 -0.9375
+vn -0.2673 0.0000 -0.9636
+vn -0.1917 0.0000 -0.9814
+vn -0.1220 0.0000 -0.9925
+vn -0.0583 0.0000 -0.9983
+vn 0.0583 0.0000 -0.9983
+vn 0.1220 0.0000 -0.9925
+vn 0.1919 0.0000 -0.9814
+vn 0.2677 0.0000 -0.9635
+vn 0.3486 0.0000 -0.9373
+vn 0.4330 0.0000 -0.9014
+vn 0.5190 0.0000 -0.8548
+vn 0.6035 0.0000 -0.7973
+vn 0.6836 0.0000 -0.7298
+vn 0.7565 0.0000 -0.6539
+vn 0.8199 0.0000 -0.5724
+vn 0.8704 0.0000 -0.4924
+s off
+f 10//1 12//1 11//1
+f 10//1 13//1 12//1
+f 10//1 14//1 13//1
+f 10//1 1//1 14//1
+f 10//1 63//1 1//1
+f 63//1 62//1 1//1
+f 62//1 2//1 1//1
+f 61//1 2//1 62//1
+f 60//1 2//1 61//1
+f 10//1 64//1 63//1
+f 59//1 2//1 60//1
+f 10//1 65//1 64//1
+f 58//1 2//1 59//1
+f 10//1 66//1 65//1
+f 58//1 178//1 2//1
+f 178//1 176//1 2//1
+f 176//1 3//1 2//1
+f 57//1 178//1 58//1
+f 10//1 67//1 66//1
+f 56//1 178//1 57//1
+f 10//1 68//1 67//1
+f 9//1 75//1 10//1
+f 75//1 74//1 10//1
+f 74//1 73//1 10//1
+f 73//1 72//1 10//1
+f 72//1 71//1 10//1
+f 71//1 70//1 10//1
+f 70//1 69//1 10//1
+f 69//1 68//1 10//1
+f 55//1 178//1 56//1
+f 54//1 179//1 55//1
+f 179//1 178//1 55//1
+f 54//1 180//1 179//1
+f 177//1 176//1 178//1
+f 53//1 180//1 54//1
+f 52//1 180//1 53//1
+f 51//1 180//1 52//1
+f 50//1 180//1 51//1
+f 49//1 180//1 50//1
+f 314//1 316//1 315//1
+f 313//1 316//1 314//1
+f 313//1 317//1 316//1
+f 313//1 318//1 317//1
+f 312//1 318//1 313//1
+f 312//1 319//1 318//1
+f 311//1 319//1 312//1
+f 48//1 180//1 49//1
+f 9//1 76//1 75//1
+f 311//1 320//1 319//1
+f 310//1 320//1 311//1
+f 310//1 321//1 320//1
+f 309//1 321//1 310//1
+f 309//1 322//1 321//1
+f 308//1 322//1 309//1
+f 308//1 323//1 322//1
+f 307//1 323//1 308//1
+f 47//1 180//1 48//1
+f 9//1 77//1 76//1
+f 307//1 324//1 323//1
+f 306//1 324//1 307//1
+f 306//1 325//1 324//1
+f 305//1 325//1 306//1
+f 46//1 180//1 47//1
+f 9//1 78//1 77//1
+f 305//1 326//1 325//1
+f 304//1 326//1 305//1
+f 304//1 327//1 326//1
+f 303//1 327//1 304//1
+f 45//1 180//1 46//1
+f 9//1 79//1 78//1
+f 302//1 327//1 303//1
+f 302//1 232//1 327//1
+f 301//1 232//1 302//1
+f 301//1 233//1 232//1
+f 44//1 181//1 45//1
+f 181//1 180//1 45//1
+f 9//1 80//1 79//1
+f 300//1 233//1 301//1
+f 300//1 234//1 233//1
+f 44//1 182//1 181//1
+f 175//1 3//1 176//1
+f 299//1 234//1 300//1
+f 299//1 235//1 234//1
+f 43//1 182//1 44//1
+f 9//1 81//1 80//1
+f 298//1 235//1 299//1
+f 298//1 236//1 235//1
+f 42//1 182//1 43//1
+f 9//1 82//1 81//1
+f 297//1 236//1 298//1
+f 297//1 237//1 236//1
+f 296//1 237//1 297//1
+f 296//1 238//1 237//1
+f 41//1 182//1 42//1
+f 9//1 83//1 82//1
+f 295//1 238//1 296//1
+f 295//1 239//1 238//1
+f 40//1 182//1 41//1
+f 9//1 84//1 83//1
+f 294//1 239//1 295//1
+f 294//1 240//1 239//1
+f 40//1 183//1 182//1
+f 40//1 184//1 183//1
+f 173//1 175//1 174//1
+f 173//1 3//1 175//1
+f 293//1 240//1 294//1
+f 293//1 241//1 240//1
+f 40//1 185//1 184//1
+f 39//1 185//1 40//1
+f 9//1 85//1 84//1
+f 292//1 241//1 293//1
+f 292//1 242//1 241//1
+f 39//1 186//1 185//1
+f 38//1 186//1 39//1
+f 9//1 86//1 85//1
+f 291//1 242//1 292//1
+f 291//1 243//1 242//1
+f 38//1 187//1 186//1
+f 290//1 243//1 291//1
+f 37//1 187//1 38//1
+f 9//1 87//1 86//1
+f 290//1 244//1 243//1
+f 37//1 188//1 187//1
+f 36//1 188//1 37//1
+f 289//1 244//1 290//1
+f 289//1 245//1 244//1
+f 9//1 88//1 87//1
+f 35//1 188//1 36//1
+f 35//1 189//1 188//1
+f 288//1 245//1 289//1
+f 288//1 246//1 245//1
+f 34//1 189//1 35//1
+f 9//1 89//1 88//1
+f 287//1 246//1 288//1
+f 287//1 247//1 246//1
+f 34//1 190//1 189//1
+f 33//1 190//1 34//1
+f 286//1 247//1 287//1
+f 286//1 248//1 247//1
+f 9//1 90//1 89//1
+f 33//1 191//1 190//1
+f 32//1 191//1 33//1
+f 285//1 248//1 286//1
+f 285//1 249//1 248//1
+f 31//1 191//1 32//1
+f 31//1 192//1 191//1
+f 9//1 91//1 90//1
+f 284//1 249//1 285//1
+f 284//1 250//1 249//1
+f 30//1 192//1 31//1
+f 30//1 193//1 192//1
+f 283//1 250//1 284//1
+f 283//1 251//1 250//1
+f 9//1 92//1 91//1
+f 29//1 193//1 30//1
+f 29//1 194//1 193//1
+f 172//1 3//1 173//1
+f 282//1 251//1 283//1
+f 282//1 252//1 251//1
+f 29//1 195//1 194//1
+f 171//1 3//1 172//1
+f 29//1 196//1 195//1
+f 28//1 196//1 29//1
+f 9//1 93//1 92//1
+f 170//1 3//1 171//1
+f 281//1 252//1 282//1
+f 281//1 253//1 252//1
+f 27//1 196//1 28//1
+f 169//1 3//1 170//1
+f 27//1 197//1 196//1
+f 280//1 253//1 281//1
+f 280//1 254//1 253//1
+f 168//1 137//1 169//1
+f 137//1 3//1 169//1
+f 9//1 94//1 93//1
+f 26//1 197//1 27//1
+f 167//1 137//1 168//1
+f 279//1 254//1 280//1
+f 279//1 255//1 254//1
+f 26//1 198//1 197//1
+f 166//1 137//1 167//1
+f 25//1 198//1 26//1
+f 278//1 255//1 279//1
+f 278//1 256//1 255//1
+f 165//1 137//1 166//1
+f 9//1 95//1 94//1
+f 25//1 199//1 198//1
+f 164//1 137//1 165//1
+f 277//1 256//1 278//1
+f 277//1 257//1 256//1
+f 24//1 199//1 25//1
+f 163//1 137//1 164//1
+f 276//1 257//1 277//1
+f 276//1 258//1 257//1
+f 162//1 137//1 163//1
+f 24//1 200//1 199//1
+f 161//1 137//1 162//1
+f 23//1 200//1 24//1
+f 9//1 96//1 95//1
+f 275//1 258//1 276//1
+f 275//1 259//1 258//1
+f 160//1 137//1 161//1
+f 159//1 137//1 160//1
+f 274//1 259//1 275//1
+f 158//1 137//1 159//1
+f 274//1 260//1 259//1
+f 22//1 200//1 23//1
+f 157//1 137//1 158//1
+f 22//1 201//1 200//1
+f 156//1 137//1 157//1
+f 273//1 260//1 274//1
+f 273//1 261//1 260//1
+f 155//1 137//1 156//1
+f 9//1 97//1 96//1
+f 154//1 137//1 155//1
+f 153//1 137//1 154//1
+f 153//1 138//1 137//1
+f 231//1 3//1 137//1
+f 153//1 139//1 138//1
+f 153//1 140//1 139//1
+f 272//1 261//1 273//1
+f 153//1 141//1 140//1
+f 152//1 141//1 153//1
+f 272//1 262//1 261//1
+f 152//1 142//1 141//1
+f 152//1 143//1 142//1
+f 21//1 201//1 22//1
+f 151//1 143//1 152//1
+f 151//1 144//1 143//1
+f 151//1 145//1 144//1
+f 151//1 146//1 145//1
+f 150//1 146//1 151//1
+f 150//1 147//1 146//1
+f 150//1 148//1 147//1
+f 149//1 148//1 150//1
+f 21//1 202//1 201//1
+f 271//1 262//1 272//1
+f 271//1 263//1 262//1
+f 270//1 263//1 271//1
+f 270//1 264//1 263//1
+f 269//1 264//1 270//1
+f 269//1 265//1 264//1
+f 20//1 202//1 21//1
+f 9//1 98//1 97//1
+f 268//1 265//1 269//1
+f 268//1 266//1 265//1
+f 267//1 266//1 268//1
+f 20//1 203//1 202//1
+f 19//1 203//1 20//1
+f 19//1 204//1 203//1
+f 9//1 99//1 98//1
+f 18//1 204//1 19//1
+f 18//1 205//1 204//1
+f 17//1 205//1 18//1
+f 9//1 100//1 99//1
+f 17//1 206//1 205//1
+f 16//1 206//1 17//1
+f 9//1 101//1 100//1
+f 16//1 207//1 206//1
+f 15//1 207//1 16//1
+f 15//1 208//1 207//1
+f 136//1 208//1 15//1
+f 9//1 102//1 101//1
+f 136//1 209//1 208//1
+f 135//1 209//1 136//1
+f 134//1 209//1 135//1
+f 134//1 210//1 209//1
+f 9//1 103//1 102//1
+f 133//1 210//1 134//1
+f 133//1 211//1 210//1
+f 133//1 212//1 211//1
+f 9//1 104//1 103//1
+f 132//1 212//1 133//1
+f 132//1 213//1 212//1
+f 230//1 3//1 231//1
+f 229//1 3//1 230//1
+f 132//1 214//1 213//1
+f 228//1 3//1 229//1
+f 9//1 105//1 104//1
+f 227//1 3//1 228//1
+f 132//1 215//1 214//1
+f 226//1 3//1 227//1
+f 131//1 215//1 132//1
+f 225//1 3//1 226//1
+f 131//1 216//1 215//1
+f 224//1 3//1 225//1
+f 131//1 217//1 216//1
+f 223//1 3//1 224//1
+f 9//1 106//1 105//1
+f 222//1 3//1 223//1
+f 131//1 218//1 217//1
+f 221//1 3//1 222//1
+f 220//1 3//1 221//1
+f 131//1 219//1 218//1
+f 219//1 3//1 220//1
+f 131//1 3//1 219//1
+f 9//1 107//1 106//1
+f 130//1 3//1 131//1
+f 121//1 123//1 122//1
+f 9//1 108//1 107//1
+f 120//1 123//1 121//1
+f 119//1 123//1 120//1
+f 118//1 123//1 119//1
+f 117//1 123//1 118//1
+f 9//1 109//1 108//1
+f 116//1 123//1 117//1
+f 115//1 123//1 116//1
+f 114//1 123//1 115//1
+f 113//1 123//1 114//1
+f 9//1 110//1 109//1
+f 112//1 123//1 113//1
+f 111//1 123//1 112//1
+f 110//1 123//1 111//1
+f 9//1 123//1 110//1
+f 129//1 3//1 130//1
+f 128//1 3//1 129//1
+f 128//1 4//1 3//1
+f 127//1 4//1 128//1
+f 8//1 123//1 9//1
+f 126//1 4//1 127//1
+f 125//1 4//1 126//1
+f 124//1 4//1 125//1
+f 123//1 4//1 124//1
+f 7//1 123//1 8//1
+f 7//1 4//1 123//1
+f 6//2 4//2 7//2
+f 5//3 4//3 6//3
+f 339//4 337//4 338//4
+f 340//4 337//4 339//4
+f 341//4 337//4 340//4
+f 328//4 337//4 341//4
+f 390//4 337//4 328//4
+f 389//4 390//4 328//4
+f 329//4 389//4 328//4
+f 329//4 388//4 389//4
+f 329//4 387//4 388//4
+f 391//4 337//4 390//4
+f 329//4 386//4 387//4
+f 392//4 337//4 391//4
+f 329//4 385//4 386//4
+f 393//4 337//4 392//4
+f 505//4 385//4 329//4
+f 503//4 505//4 329//4
+f 330//4 503//4 329//4
+f 505//4 384//4 385//4
+f 394//4 337//4 393//4
+f 505//4 383//4 384//4
+f 395//4 337//4 394//4
+f 402//4 336//4 337//4
+f 401//4 402//4 337//4
+f 400//4 401//4 337//4
+f 399//4 400//4 337//4
+f 398//4 399//4 337//4
+f 397//4 398//4 337//4
+f 396//4 397//4 337//4
+f 395//4 396//4 337//4
+f 505//4 382//4 383//4
+f 506//4 381//4 382//4
+f 505//4 506//4 382//4
+f 507//4 381//4 506//4
+f 503//4 504//4 505//4
+f 507//4 380//4 381//4
+f 507//4 379//4 380//4
+f 507//4 378//4 379//4
+f 507//4 377//4 378//4
+f 507//4 376//4 377//4
+f 643//4 641//4 642//4
+f 643//4 640//4 641//4
+f 644//4 640//4 643//4
+f 645//4 640//4 644//4
+f 645//4 639//4 640//4
+f 646//4 639//4 645//4
+f 646//4 638//4 639//4
+f 507//4 375//4 376//4
+f 403//4 336//4 402//4
+f 647//4 638//4 646//4
+f 647//4 637//4 638//4
+f 648//4 637//4 647//4
+f 648//4 636//4 637//4
+f 649//4 636//4 648//4
+f 649//4 635//4 636//4
+f 650//4 635//4 649//4
+f 650//4 634//4 635//4
+f 507//4 374//4 375//4
+f 404//4 336//4 403//4
+f 651//4 634//4 650//4
+f 651//4 633//4 634//4
+f 652//4 633//4 651//4
+f 652//4 632//4 633//4
+f 507//4 373//4 374//4
+f 405//4 336//4 404//4
+f 653//4 632//4 652//4
+f 653//4 631//4 632//4
+f 654//4 631//4 653//4
+f 654//4 630//4 631//4
+f 507//4 372//4 373//4
+f 406//4 336//4 405//4
+f 654//4 629//4 630//4
+f 559//4 629//4 654//4
+f 559//4 628//4 629//4
+f 560//4 628//4 559//4
+f 508//4 371//4 372//4
+f 507//4 508//4 372//4
+f 407//4 336//4 406//4
+f 560//4 627//4 628//4
+f 561//4 627//4 560//4
+f 509//4 371//4 508//4
+f 330//4 502//4 503//4
+f 561//4 626//4 627//4
+f 562//4 626//4 561//4
+f 509//4 370//4 371//4
+f 408//4 336//4 407//4
+f 562//4 625//4 626//4
+f 563//4 625//4 562//4
+f 509//4 369//4 370//4
+f 409//4 336//4 408//4
+f 563//4 624//4 625//4
+f 564//4 624//4 563//4
+f 564//4 623//4 624//4
+f 565//4 623//4 564//4
+f 509//4 368//4 369//4
+f 410//4 336//4 409//4
+f 565//4 622//4 623//4
+f 566//4 622//4 565//4
+f 509//4 367//4 368//4
+f 411//4 336//4 410//4
+f 566//4 621//4 622//4
+f 567//4 621//4 566//4
+f 510//4 367//4 509//4
+f 511//4 367//4 510//4
+f 502//4 500//4 501//4
+f 330//4 500//4 502//4
+f 567//4 620//4 621//4
+f 568//4 620//4 567//4
+f 512//4 367//4 511//4
+f 512//4 366//4 367//4
+f 412//4 336//4 411//4
+f 568//4 619//4 620//4
+f 569//4 619//4 568//4
+f 513//4 366//4 512//4
+f 513//4 365//4 366//4
+f 413//4 336//4 412//4
+f 569//4 618//4 619//4
+f 570//4 618//4 569//4
+f 514//4 365//4 513//4
+f 570//4 617//4 618//4
+f 514//4 364//4 365//4
+f 414//4 336//4 413//4
+f 571//4 617//4 570//4
+f 515//4 364//4 514//4
+f 515//4 363//4 364//4
+f 571//4 616//4 617//4
+f 572//4 616//4 571//4
+f 415//4 336//4 414//4
+f 515//4 362//4 363//4
+f 516//4 362//4 515//4
+f 572//4 615//4 616//4
+f 573//4 615//4 572//4
+f 516//4 361//4 362//4
+f 416//4 336//4 415//4
+f 573//4 614//4 615//4
+f 574//4 614//4 573//4
+f 517//4 361//4 516//4
+f 517//4 360//4 361//4
+f 574//4 613//4 614//4
+f 575//4 613//4 574//4
+f 417//4 336//4 416//4
+f 518//4 360//4 517//4
+f 518//4 359//4 360//4
+f 575//4 612//4 613//4
+f 576//4 612//4 575//4
+f 518//4 358//4 359//4
+f 519//4 358//4 518//4
+f 418//4 336//4 417//4
+f 576//4 611//4 612//4
+f 577//4 611//4 576//4
+f 519//4 357//4 358//4
+f 520//4 357//4 519//4
+f 577//4 610//4 611//4
+f 578//4 610//4 577//4
+f 419//4 336//4 418//4
+f 520//4 356//4 357//4
+f 521//4 356//4 520//4
+f 330//4 499//4 500//4
+f 578//4 609//4 610//4
+f 579//4 609//4 578//4
+f 522//4 356//4 521//4
+f 330//4 498//4 499//4
+f 523//4 356//4 522//4
+f 523//4 355//4 356//4
+f 420//4 336//4 419//4
+f 330//4 497//4 498//4
+f 579//4 608//4 609//4
+f 580//4 608//4 579//4
+f 523//4 354//4 355//4
+f 330//4 496//4 497//4
+f 524//4 354//4 523//4
+f 580//4 607//4 608//4
+f 581//4 607//4 580//4
+f 464//4 495//4 496//4
+f 330//4 464//4 496//4
+f 421//4 336//4 420//4
+f 524//4 353//4 354//4
+f 464//4 494//4 495//4
+f 581//4 606//4 607//4
+f 582//4 606//4 581//4
+f 525//4 353//4 524//4
+f 464//4 493//4 494//4
+f 525//4 352//4 353//4
+f 582//4 605//4 606//4
+f 583//4 605//4 582//4
+f 464//4 492//4 493//4
+f 422//4 336//4 421//4
+f 526//4 352//4 525//4
+f 464//4 491//4 492//4
+f 583//4 604//4 605//4
+f 584//4 604//4 583//4
+f 526//4 351//4 352//4
+f 464//4 490//4 491//4
+f 584//4 603//4 604//4
+f 585//4 603//4 584//4
+f 464//4 489//4 490//4
+f 527//4 351//4 526//4
+f 464//4 488//4 489//4
+f 527//4 350//4 351//4
+f 423//4 336//4 422//4
+f 585//4 602//4 603//4
+f 586//4 602//4 585//4
+f 464//4 487//4 488//4
+f 464//4 486//4 487//4
+f 586//4 601//4 602//4
+f 464//4 485//4 486//4
+f 587//4 601//4 586//4
+f 527//4 349//4 350//4
+f 464//4 484//4 485//4
+f 528//4 349//4 527//4
+f 464//4 483//4 484//4
+f 587//4 600//4 601//4
+f 588//4 600//4 587//4
+f 464//4 482//4 483//4
+f 424//4 336//4 423//4
+f 464//4 481//4 482//4
+f 464//4 480//4 481//4
+f 465//4 480//4 464//4
+f 330//4 558//4 464//4
+f 466//4 480//4 465//4
+f 467//4 480//4 466//4
+f 588//4 599//4 600//4
+f 468//4 480//4 467//4
+f 468//4 479//4 480//4
+f 589//4 599//4 588//4
+f 469//4 479//4 468//4
+f 470//4 479//4 469//4
+f 528//4 348//4 349//4
+f 470//4 478//4 479//4
+f 471//4 478//4 470//4
+f 472//4 478//4 471//4
+f 473//4 478//4 472//4
+f 473//4 477//4 478//4
+f 474//4 477//4 473//4
+f 475//5 477//5 474//5
+f 475//6 476//6 477//6
+f 529//4 348//4 528//4
+f 589//4 598//4 599//4
+f 590//4 598//4 589//4
+f 590//4 597//4 598//4
+f 591//4 597//4 590//4
+f 591//4 596//4 597//4
+f 592//4 596//4 591//4
+f 529//4 347//4 348//4
+f 425//4 336//4 424//4
+f 592//4 595//4 596//4
+f 593//4 595//4 592//4
+f 593//4 594//4 595//4
+f 530//4 347//4 529//4
+f 530//4 346//4 347//4
+f 531//4 346//4 530//4
+f 426//4 336//4 425//4
+f 531//4 345//4 346//4
+f 532//4 345//4 531//4
+f 532//4 344//4 345//4
+f 427//4 336//4 426//4
+f 533//4 344//4 532//4
+f 533//4 343//4 344//4
+f 428//4 336//4 427//4
+f 534//4 343//4 533//4
+f 534//4 342//4 343//4
+f 535//4 342//4 534//4
+f 535//4 463//4 342//4
+f 429//4 336//4 428//4
+f 536//4 463//4 535//4
+f 536//4 462//4 463//4
+f 536//4 461//4 462//4
+f 537//4 461//4 536//4
+f 430//4 336//4 429//4
+f 537//4 460//4 461//4
+f 538//4 460//4 537//4
+f 539//4 460//4 538//4
+f 431//4 336//4 430//4
+f 539//4 459//4 460//4
+f 540//4 459//4 539//4
+f 330//4 557//4 558//4
+f 330//4 556//4 557//4
+f 541//4 459//4 540//4
+f 330//4 555//4 556//4
+f 432//4 336//4 431//4
+f 330//4 554//4 555//4
+f 542//4 459//4 541//4
+f 330//4 553//4 554//4
+f 542//4 458//4 459//4
+f 330//4 552//4 553//4
+f 543//4 458//4 542//4
+f 330//4 551//4 552//4
+f 544//4 458//4 543//4
+f 330//4 550//4 551//4
+f 433//4 336//4 432//4
+f 330//4 549//4 550//4
+f 545//4 458//4 544//4
+f 330//4 548//4 549//4
+f 330//4 547//4 548//4
+f 546//4 458//4 545//4
+f 330//4 546//4 547//4
+f 330//4 458//4 546//4
+f 434//4 336//4 433//4
+f 330//4 457//4 458//4
+f 450//4 448//4 449//4
+f 435//4 336//4 434//4
+f 450//4 447//4 448//4
+f 450//4 446//4 447//4
+f 450//4 445//4 446//4
+f 450//4 444//4 445//4
+f 436//4 336//4 435//4
+f 450//4 443//4 444//4
+f 450//4 442//4 443//4
+f 450//4 441//4 442//4
+f 450//4 440//4 441//4
+f 437//4 336//4 436//4
+f 450//4 439//4 440//4
+f 450//4 438//4 439//4
+f 450//4 437//4 438//4
+f 450//4 336//4 437//4
+f 330//4 456//4 457//4
+f 330//4 455//4 456//4
+f 331//4 455//4 330//4
+f 331//4 454//4 455//4
+f 450//4 335//4 336//4
+f 331//4 453//4 454//4
+f 331//4 452//4 453//4
+f 331//4 451//4 452//4
+f 331//4 450//4 451//4
+f 450//4 334//4 335//4
+f 331//4 334//4 450//4
+f 331//2 333//2 334//2
+f 331//3 332//3 333//3
+s 1
+f 658//7 655//7 656//7
+f 660//8 657//7 658//7
+f 662//9 659//8 660//8
+f 664//2 661//9 662//9
+f 666//2 663//2 664//2
+f 668//10 665//2 666//2
+f 670//11 667//10 668//10
+f 672//11 669//11 670//11
+f 674//12 671//11 672//11
+f 676//13 673//12 674//12
+f 678//3 675//13 676//13
+f 680//3 677//3 678//3
+f 682//14 679//3 680//3
+f 656//7 681//14 682//14
+f 686//15 683//16 684//16
+f 688//17 685//15 686//15
+f 690//18 687//17 688//17
+f 692//19 689//18 690//18
+f 694//20 691//19 692//19
+f 696//21 693//20 694//20
+f 698//22 695//23 696//21
+f 700//24 697//22 698//22
+f 702//25 699//24 700//24
+f 704//26 701//25 702//25
+f 706//27 703//26 704//26
+f 708//28 705//27 706//27
+f 710//29 707//28 708//28
+f 712//30 709//29 710//29
+f 714//31 711//30 712//30
+f 716//32 713//31 714//31
+f 718//33 715//32 716//32
+f 720//34 717//33 718//33
+f 722//35 719//34 720//34
+f 724//36 721//35 722//35
+f 726//37 723//36 724//36
+f 728//38 725//37 726//37
+f 730//39 727//38 728//38
+f 732//40 729//39 730//39
+f 734//41 731//40 732//40
+f 736//42 733//41 734//41
+f 738//43 735//42 736//42
+f 740//44 737//43 738//43
+f 742//45 739//44 740//44
+f 744//46 741//45 742//45
+f 746//47 743//46 744//46
+f 748//48 745//47 746//47
+f 750//49 747//48 748//48
+f 752//50 749//49 750//49
+f 754//51 751//50 752//50
+f 756//52 753//51 754//51
+f 758//53 755//52 756//52
+f 760//54 757//53 758//53
+f 762//55 759//54 760//54
+f 764//56 761//55 762//55
+f 766//57 763//56 764//56
+f 768//58 765//57 766//57
+f 770//59 767//58 768//58
+f 772//60 769//59 770//59
+f 774//61 771//60 772//60
+f 776//62 773//61 774//61
+f 778//63 775//62 776//62
+f 780//64 777//63 778//63
+f 782//65 779//64 780//64
+f 784//66 781//65 782//65
+f 786//67 783//66 784//66
+f 788//68 785//67 786//67
+f 790//69 787//68 788//68
+f 792//70 789//69 790//69
+f 794//71 791//70 792//70
+f 796//72 793//71 794//71
+f 798//73 795//72 796//72
+f 800//74 797//73 798//73
+f 802//75 799//74 800//74
+f 804//76 801//75 802//75
+f 806//77 803//76 804//76
+f 808//78 805//77 806//77
+f 810//79 807//78 808//78
+f 812//80 809//79 810//79
+f 814//81 811//80 812//80
+f 816//82 813//81 814//81
+f 818//83 815//82 816//82
+f 820//84 817//83 818//83
+f 822//85 819//84 820//84
+f 824//86 821//85 822//85
+f 826//87 823//86 824//86
+f 828//88 825//87 826//87
+f 830//89 827//88 828//88
+f 832//90 829//89 830//89
+f 834//91 831//90 832//90
+f 836//92 833//91 834//91
+f 838//93 835//92 836//92
+f 840//94 837//93 838//93
+f 842//95 839//94 840//94
+f 844//96 841//95 842//95
+f 846//97 843//96 844//96
+f 848//98 845//97 846//97
+f 850//99 847//98 848//98
+f 852//100 849//99 850//99
+f 854//101 851//100 852//100
+f 856//102 853//101 854//101
+f 858//103 855//102 856//102
+f 860//104 857//103 858//103
+f 862//105 859//104 860//104
+f 864//106 861//105 862//105
+f 866//107 863//106 864//106
+f 868//108 865//107 866//107
+f 870//109 867//108 868//108
+f 872//110 869//109 870//109
+f 874//111 871//110 872//110
+f 876//112 873//111 874//111
+f 878//113 875//112 876//112
+f 880//114 877//113 878//113
+f 882//115 879//114 880//114
+f 884//116 881//115 882//115
+f 886//117 883//116 884//116
+f 888//118 885//117 886//117
+f 890//119 887//118 888//118
+f 892//120 889//119 890//119
+f 894//121 891//122 892//120
+f 896//123 893//121 894//121
+f 898//124 895//123 896//123
+f 900//125 897//124 898//124
+f 902//126 899//125 900//125
+f 904//127 901//126 902//126
+f 906//127 903//127 904//127
+f 908//127 905//127 906//127
+f 910//127 907//127 908//127
+f 912//127 909//127 910//127
+f 914//127 911//127 912//127
+f 916//127 913//127 914//127
+f 918//127 915//127 916//127
+f 920//127 917//127 918//127
+f 922//127 919//127 920//127
+f 924//127 921//127 922//127
+f 926//128 923//127 924//127
+f 684//16 925//128 926//128
+f 930//129 927//130 928//130
+f 932//129 929//129 930//129
+f 934//129 931//129 932//129
+f 936//129 933//129 934//129
+f 938//129 935//129 936//129
+f 940//129 937//129 938//129
+f 942//129 939//129 940//129
+f 944//129 941//129 942//129
+f 946//129 943//129 944//129
+f 948//129 945//129 946//129
+f 950//131 947//129 948//129
+f 952//132 949//129 950//131
+f 954//133 951//134 952//132
+f 956//135 953//133 954//133
+f 958//136 955//135 956//135
+f 960//137 957//136 958//136
+f 962//138 959//137 960//137
+f 964//139 961//138 962//138
+f 966//140 963//139 964//139
+f 968//141 965//140 966//140
+f 970//142 967//141 968//141
+f 972//143 969//142 970//142
+f 974//144 971//143 972//143
+f 976//145 973//144 974//144
+f 978//146 975//145 976//145
+f 980//147 977//146 978//146
+f 982//148 979//147 980//147
+f 984//149 981//148 982//148
+f 986//150 983//149 984//149
+f 988//151 985//150 986//150
+f 990//152 987//151 988//151
+f 992//153 989//152 990//152
+f 994//154 991//153 992//153
+f 996//155 993//154 994//154
+f 998//156 995//155 996//155
+f 1000//157 997//156 998//156
+f 1002//158 999//157 1000//157
+f 1004//158 1001//158 1002//158
+f 1006//10 1003//158 1004//158
+f 1008//10 1005//10 1006//10
+f 1010//10 1007//10 1008//10
+f 1012//159 1009//10 1010//10
+f 1014//159 1011//159 1012//159
+f 1016//159 1013//159 1014//159
+f 1018//14 1015//159 1016//159
+f 1020//14 1017//14 1018//14
+f 1022//7 1019//14 1020//14
+f 1024//7 1021//7 1022//7
+f 1026//7 1023//7 1024//7
+f 1028//7 1025//7 1026//7
+f 1030//7 1027//7 1028//7
+f 1032//7 1029//7 1030//7
+f 1034//7 1031//7 1032//7
+f 1036//7 1033//7 1034//7
+f 1038//7 1035//7 1036//7
+f 1040//7 1037//7 1038//7
+f 1042//7 1039//7 1040//7
+f 1044//160 1041//7 1042//7
+f 1046//161 1043//160 1044//160
+f 1048//162 1045//161 1046//161
+f 1050//163 1047//162 1048//162
+f 1052//164 1049//163 1050//163
+f 1054//165 1051//164 1052//164
+f 1056//166 1053//165 1054//165
+f 1058//167 1055//166 1056//166
+f 1060//168 1057//167 1058//167
+f 1062//96 1059//168 1060//168
+f 1064//169 1061//96 1062//96
+f 1066//170 1063//169 1064//169
+f 1068//171 1065//170 1066//170
+f 1070//172 1067//171 1068//171
+f 1072//173 1069//172 1070//172
+f 1074//174 1071//173 1072//173
+f 1076//175 1073//174 1074//174
+f 1078//176 1075//175 1076//175
+f 1080//177 1077//176 1078//176
+f 1082//178 1079//179 1080//177
+f 1084//180 1081//178 1082//178
+f 1086//181 1083//180 1084//180
+f 1088//182 1085//181 1086//181
+f 1090//183 1087//182 1088//182
+f 1092//184 1089//183 1090//183
+f 1094//185 1091//184 1092//184
+f 1096//186 1093//185 1094//185
+f 1098//187 1095//186 1096//186
+f 1100//188 1097//187 1098//187
+f 1102//189 1099//188 1100//188
+f 1104//190 1101//189 1102//189
+f 1106//191 1103//190 1104//190
+f 1108//192 1105//191 1106//191
+f 1110//193 1107//192 1108//192
+f 1112//194 1109//193 1110//193
+f 1114//195 1111//194 1112//194
+f 1116//196 1113//195 1114//195
+f 928//130 1115//196 1116//196
+f 1120//197 1117//198 1118//198
+f 1122//199 1119//197 1120//197
+f 1124//200 1121//199 1122//199
+f 1126//201 1123//200 1124//200
+f 1128//202 1125//201 1126//201
+f 1130//203 1127//202 1128//202
+f 1132//204 1129//203 1130//203
+f 1134//205 1131//204 1132//204
+f 1136//206 1133//205 1134//205
+f 1138//207 1135//206 1136//206
+f 1140//7 1137//207 1138//207
+f 1142//208 1139//7 1140//7
+f 1144//209 1141//208 1142//208
+f 1146//210 1143//209 1144//209
+f 1148//211 1145//210 1146//210
+f 1150//212 1147//211 1148//211
+f 1152//213 1149//212 1150//212
+f 1154//214 1151//213 1152//213
+f 1156//215 1153//214 1154//214
+f 1158//216 1155//215 1156//215
+f 1160//217 1157//216 1158//216
+f 1162//218 1159//217 1160//217
+f 1164//219 1161//218 1162//218
+f 1166//220 1163//219 1164//219
+f 1168//221 1165//220 1166//220
+f 1170//222 1167//221 1168//221
+f 1172//223 1169//222 1170//222
+f 1174//224 1171//223 1172//223
+f 1176//225 1173//224 1174//224
+f 1178//226 1175//225 1176//225
+f 1180//227 1177//226 1178//226
+f 1182//228 1179//227 1180//227
+f 1184//229 1181//228 1182//228
+f 1186//230 1183//229 1184//229
+f 1188//231 1185//230 1186//230
+f 1190//232 1187//231 1188//231
+f 1192//233 1189//232 1190//232
+f 1194//234 1191//233 1192//233
+f 1196//235 1193//236 1194//234
+f 1198//237 1195//235 1196//235
+f 1200//238 1197//237 1198//237
+f 1202//239 1199//238 1200//238
+f 1204//240 1201//239 1202//239
+f 1206//241 1203//240 1204//240
+f 1208//242 1205//241 1206//241
+f 1210//243 1207//242 1208//242
+f 1212//244 1209//243 1210//243
+f 1214//245 1211//244 1212//244
+f 1216//246 1213//245 1214//245
+f 1218//247 1215//246 1216//246
+f 1220//248 1217//247 1218//247
+f 1222//249 1219//248 1220//248
+f 1224//250 1221//249 1222//249
+f 1226//251 1223//250 1224//250
+f 1228//252 1225//251 1226//251
+f 1230//253 1227//252 1228//252
+f 1232//254 1229//253 1230//253
+f 1234//255 1231//254 1232//254
+f 1236//256 1233//255 1234//255
+f 1238//257 1235//256 1236//256
+f 1240//258 1237//257 1238//257
+f 1242//259 1239//258 1240//258
+f 1244//260 1241//259 1242//259
+f 1246//261 1243//260 1244//260
+f 1248//262 1245//261 1246//261
+f 1250//263 1247//262 1248//262
+f 1252//264 1249//263 1250//263
+f 1254//265 1251//264 1252//264
+f 1256//266 1253//265 1254//265
+f 1258//267 1255//266 1256//266
+f 1260//268 1257//267 1258//267
+f 1262//269 1259//268 1260//268
+f 1264//270 1261//269 1262//269
+f 1266//271 1263//270 1264//270
+f 1268//272 1265//271 1266//271
+f 1270//273 1267//272 1268//272
+f 1272//274 1269//273 1270//273
+f 1274//275 1271//274 1272//274
+f 1276//276 1273//275 1274//275
+f 1278//277 1275//276 1276//276
+f 1280//278 1277//277 1278//277
+f 1282//279 1279//278 1280//278
+f 1284//3 1281//279 1282//279
+f 1286//280 1283//3 1284//3
+f 1288//281 1285//280 1286//280
+f 1290//282 1287//281 1288//281
+f 1292//283 1289//282 1290//282
+f 1294//284 1291//283 1292//283
+f 1296//285 1293//284 1294//284
+f 1298//286 1295//285 1296//285
+f 1300//287 1297//286 1298//286
+f 1302//288 1299//287 1300//287
+f 1304//289 1301//288 1302//288
+f 1306//290 1303//289 1304//289
+f 1308//291 1305//290 1306//290
+f 1118//198 1307//291 1308//291
+f 658//7 657//7 655//7
+f 660//8 659//8 657//7
+f 662//9 661//9 659//8
+f 664//2 663//2 661//9
+f 666//2 665//2 663//2
+f 668//10 667//10 665//2
+f 670//11 669//11 667//10
+f 672//11 671//11 669//11
+f 674//12 673//12 671//11
+f 676//13 675//13 673//12
+f 678//3 677//3 675//13
+f 680//3 679//3 677//3
+f 682//14 681//14 679//3
+f 656//7 655//7 681//14
+f 686//15 685//15 683//16
+f 688//17 687//17 685//15
+f 690//18 689//18 687//17
+f 692//19 691//19 689//18
+f 694//20 693//20 691//19
+f 696//21 695//23 693//20
+f 698//22 697//22 695//23
+f 700//24 699//24 697//22
+f 702//25 701//25 699//24
+f 704//26 703//26 701//25
+f 706//27 705//27 703//26
+f 708//28 707//28 705//27
+f 710//29 709//29 707//28
+f 712//30 711//30 709//29
+f 714//31 713//31 711//30
+f 716//32 715//32 713//31
+f 718//33 717//33 715//32
+f 720//34 719//34 717//33
+f 722//35 721//35 719//34
+f 724//36 723//36 721//35
+f 726//37 725//37 723//36
+f 728//38 727//38 725//37
+f 730//39 729//39 727//38
+f 732//40 731//40 729//39
+f 734//41 733//41 731//40
+f 736//42 735//42 733//41
+f 738//43 737//43 735//42
+f 740//44 739//44 737//43
+f 742//45 741//45 739//44
+f 744//46 743//46 741//45
+f 746//47 745//47 743//46
+f 748//48 747//48 745//47
+f 750//49 749//49 747//48
+f 752//50 751//50 749//49
+f 754//51 753//51 751//50
+f 756//52 755//52 753//51
+f 758//53 757//53 755//52
+f 760//54 759//54 757//53
+f 762//55 761//55 759//54
+f 764//56 763//56 761//55
+f 766//57 765//57 763//56
+f 768//58 767//58 765//57
+f 770//59 769//59 767//58
+f 772//60 771//60 769//59
+f 774//61 773//61 771//60
+f 776//62 775//62 773//61
+f 778//63 777//63 775//62
+f 780//64 779//64 777//63
+f 782//65 781//65 779//64
+f 784//66 783//66 781//65
+f 786//67 785//67 783//66
+f 788//68 787//68 785//67
+f 790//69 789//69 787//68
+f 792//70 791//70 789//69
+f 794//71 793//71 791//70
+f 796//72 795//72 793//71
+f 798//73 797//73 795//72
+f 800//74 799//74 797//73
+f 802//75 801//75 799//74
+f 804//76 803//76 801//75
+f 806//77 805//77 803//76
+f 808//78 807//78 805//77
+f 810//79 809//79 807//78
+f 812//80 811//80 809//79
+f 814//81 813//81 811//80
+f 816//82 815//82 813//81
+f 818//83 817//83 815//82
+f 820//84 819//84 817//83
+f 822//85 821//85 819//84
+f 824//86 823//86 821//85
+f 826//87 825//87 823//86
+f 828//88 827//88 825//87
+f 830//89 829//89 827//88
+f 832//90 831//90 829//89
+f 834//91 833//91 831//90
+f 836//92 835//92 833//91
+f 838//93 837//93 835//92
+f 840//94 839//94 837//93
+f 842//95 841//95 839//94
+f 844//96 843//96 841//95
+f 846//97 845//97 843//96
+f 848//98 847//98 845//97
+f 850//99 849//99 847//98
+f 852//100 851//100 849//99
+f 854//101 853//101 851//100
+f 856//102 855//102 853//101
+f 858//103 857//103 855//102
+f 860//104 859//104 857//103
+f 862//105 861//105 859//104
+f 864//106 863//106 861//105
+f 866//107 865//107 863//106
+f 868//108 867//108 865//107
+f 870//109 869//109 867//108
+f 872//110 871//110 869//109
+f 874//111 873//111 871//110
+f 876//112 875//112 873//111
+f 878//113 877//113 875//112
+f 880//114 879//114 877//113
+f 882//115 881//115 879//114
+f 884//116 883//116 881//115
+f 886//117 885//117 883//116
+f 888//118 887//118 885//117
+f 890//119 889//119 887//118
+f 892//120 891//122 889//119
+f 894//121 893//121 891//122
+f 896//123 895//123 893//121
+f 898//124 897//124 895//123
+f 900//125 899//125 897//124
+f 902//126 901//126 899//125
+f 904//127 903//127 901//126
+f 906//127 905//127 903//127
+f 908//127 907//127 905//127
+f 910//127 909//127 907//127
+f 912//127 911//127 909//127
+f 914//127 913//127 911//127
+f 916//127 915//127 913//127
+f 918//127 917//127 915//127
+f 920//127 919//127 917//127
+f 922//127 921//127 919//127
+f 924//127 923//127 921//127
+f 926//128 925//128 923//127
+f 684//16 683//16 925//128
+f 930//129 929//129 927//130
+f 932//129 931//129 929//129
+f 934//129 933//129 931//129
+f 936//129 935//129 933//129
+f 938//129 937//129 935//129
+f 940//129 939//129 937//129
+f 942//129 941//129 939//129
+f 944//129 943//129 941//129
+f 946//129 945//129 943//129
+f 948//129 947//129 945//129
+f 950//131 949//129 947//129
+f 952//132 951//134 949//129
+f 954//133 953//133 951//134
+f 956//135 955//135 953//133
+f 958//136 957//136 955//135
+f 960//137 959//137 957//136
+f 962//138 961//138 959//137
+f 964//139 963//139 961//138
+f 966//140 965//140 963//139
+f 968//141 967//141 965//140
+f 970//142 969//142 967//141
+f 972//143 971//143 969//142
+f 974//144 973//144 971//143
+f 976//145 975//145 973//144
+f 978//146 977//146 975//145
+f 980//147 979//147 977//146
+f 982//148 981//148 979//147
+f 984//149 983//149 981//148
+f 986//150 985//150 983//149
+f 988//151 987//151 985//150
+f 990//152 989//152 987//151
+f 992//153 991//153 989//152
+f 994//154 993//154 991//153
+f 996//155 995//155 993//154
+f 998//156 997//156 995//155
+f 1000//157 999//157 997//156
+f 1002//158 1001//158 999//157
+f 1004//158 1003//158 1001//158
+f 1006//10 1005//10 1003//158
+f 1008//10 1007//10 1005//10
+f 1010//10 1009//10 1007//10
+f 1012//159 1011//159 1009//10
+f 1014//159 1013//159 1011//159
+f 1016//159 1015//159 1013//159
+f 1018//14 1017//14 1015//159
+f 1020//14 1019//14 1017//14
+f 1022//7 1021//7 1019//14
+f 1024//7 1023//7 1021//7
+f 1026//7 1025//7 1023//7
+f 1028//7 1027//7 1025//7
+f 1030//7 1029//7 1027//7
+f 1032//7 1031//7 1029//7
+f 1034//7 1033//7 1031//7
+f 1036//7 1035//7 1033//7
+f 1038//7 1037//7 1035//7
+f 1040//7 1039//7 1037//7
+f 1042//7 1041//7 1039//7
+f 1044//160 1043//160 1041//7
+f 1046//161 1045//161 1043//160
+f 1048//162 1047//162 1045//161
+f 1050//163 1049//163 1047//162
+f 1052//164 1051//164 1049//163
+f 1054//165 1053//165 1051//164
+f 1056//166 1055//166 1053//165
+f 1058//167 1057//167 1055//166
+f 1060//168 1059//168 1057//167
+f 1062//96 1061//96 1059//168
+f 1064//169 1063//169 1061//96
+f 1066//170 1065//170 1063//169
+f 1068//171 1067//171 1065//170
+f 1070//172 1069//172 1067//171
+f 1072//173 1071//173 1069//172
+f 1074//174 1073//174 1071//173
+f 1076//175 1075//175 1073//174
+f 1078//176 1077//176 1075//175
+f 1080//177 1079//179 1077//176
+f 1082//178 1081//178 1079//179
+f 1084//180 1083//180 1081//178
+f 1086//181 1085//181 1083//180
+f 1088//182 1087//182 1085//181
+f 1090//183 1089//183 1087//182
+f 1092//184 1091//184 1089//183
+f 1094//185 1093//185 1091//184
+f 1096//186 1095//186 1093//185
+f 1098//187 1097//187 1095//186
+f 1100//188 1099//188 1097//187
+f 1102//189 1101//189 1099//188
+f 1104//190 1103//190 1101//189
+f 1106//191 1105//191 1103//190
+f 1108//192 1107//192 1105//191
+f 1110//193 1109//193 1107//192
+f 1112//194 1111//194 1109//193
+f 1114//195 1113//195 1111//194
+f 1116//196 1115//196 1113//195
+f 928//130 927//130 1115//196
+f 1120//197 1119//197 1117//198
+f 1122//199 1121//199 1119//197
+f 1124//200 1123//200 1121//199
+f 1126//201 1125//201 1123//200
+f 1128//202 1127//202 1125//201
+f 1130//203 1129//203 1127//202
+f 1132//204 1131//204 1129//203
+f 1134//205 1133//205 1131//204
+f 1136//206 1135//206 1133//205
+f 1138//207 1137//207 1135//206
+f 1140//7 1139//7 1137//207
+f 1142//208 1141//208 1139//7
+f 1144//209 1143//209 1141//208
+f 1146//210 1145//210 1143//209
+f 1148//211 1147//211 1145//210
+f 1150//212 1149//212 1147//211
+f 1152//213 1151//213 1149//212
+f 1154//214 1153//214 1151//213
+f 1156//215 1155//215 1153//214
+f 1158//216 1157//216 1155//215
+f 1160//217 1159//217 1157//216
+f 1162//218 1161//218 1159//217
+f 1164//219 1163//219 1161//218
+f 1166//220 1165//220 1163//219
+f 1168//221 1167//221 1165//220
+f 1170//222 1169//222 1167//221
+f 1172//223 1171//223 1169//222
+f 1174//224 1173//224 1171//223
+f 1176//225 1175//225 1173//224
+f 1178//226 1177//226 1175//225
+f 1180//227 1179//227 1177//226
+f 1182//228 1181//228 1179//227
+f 1184//229 1183//229 1181//228
+f 1186//230 1185//230 1183//229
+f 1188//231 1187//231 1185//230
+f 1190//232 1189//232 1187//231
+f 1192//233 1191//233 1189//232
+f 1194//234 1193//236 1191//233
+f 1196//235 1195//235 1193//236
+f 1198//237 1197//237 1195//235
+f 1200//238 1199//238 1197//237
+f 1202//239 1201//239 1199//238
+f 1204//240 1203//240 1201//239
+f 1206//241 1205//241 1203//240
+f 1208//242 1207//242 1205//241
+f 1210//243 1209//243 1207//242
+f 1212//244 1211//244 1209//243
+f 1214//245 1213//245 1211//244
+f 1216//246 1215//246 1213//245
+f 1218//247 1217//247 1215//246
+f 1220//248 1219//248 1217//247
+f 1222//249 1221//249 1219//248
+f 1224//250 1223//250 1221//249
+f 1226//251 1225//251 1223//250
+f 1228//252 1227//252 1225//251
+f 1230//253 1229//253 1227//252
+f 1232//254 1231//254 1229//253
+f 1234//255 1233//255 1231//254
+f 1236//256 1235//256 1233//255
+f 1238//257 1237//257 1235//256
+f 1240//258 1239//258 1237//257
+f 1242//259 1241//259 1239//258
+f 1244//260 1243//260 1241//259
+f 1246//261 1245//261 1243//260
+f 1248//262 1247//262 1245//261
+f 1250//263 1249//263 1247//262
+f 1252//264 1251//264 1249//263
+f 1254//265 1253//265 1251//264
+f 1256//266 1255//266 1253//265
+f 1258//267 1257//267 1255//266
+f 1260//268 1259//268 1257//267
+f 1262//269 1261//269 1259//268
+f 1264//270 1263//270 1261//269
+f 1266//271 1265//271 1263//270
+f 1268//272 1267//272 1265//271
+f 1270//273 1269//273 1267//272
+f 1272//274 1271//274 1269//273
+f 1274//275 1273//275 1271//274
+f 1276//276 1275//276 1273//275
+f 1278//277 1277//277 1275//276
+f 1280//278 1279//278 1277//277
+f 1282//279 1281//279 1279//278
+f 1284//3 1283//3 1281//279
+f 1286//280 1285//280 1283//3
+f 1288//281 1287//281 1285//280
+f 1290//282 1289//282 1287//281
+f 1292//283 1291//283 1289//282
+f 1294//284 1293//284 1291//283
+f 1296//285 1295//285 1293//284
+f 1298//286 1297//286 1295//285
+f 1300//287 1299//287 1297//286
+f 1302//288 1301//288 1299//287
+f 1304//289 1303//289 1301//288
+f 1306//290 1305//290 1303//289
+f 1308//291 1307//291 1305//290
+f 1118//198 1117//198 1307//291
diff --git a/examples/vulkan/shared/trianglerenderer.cpp b/examples/vulkan/shared/trianglerenderer.cpp
new file mode 100644
index 0000000000..f346f90c89
--- /dev/null
+++ b/examples/vulkan/shared/trianglerenderer.cpp
@@ -0,0 +1,513 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "trianglerenderer.h"
+#include <QVulkanFunctions>
+#include <QFile>
+
+// Note that the vertex data and the projection matrix assume OpenGL. With
+// Vulkan Y is negated in clip space and the near/far plane is at 0/1 instead
+// of -1/1. These will be corrected for by an extra transformation when
+// calculating the modelview-projection matrix.
+static float vertexData[] = {
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f
+};
+
+static const int UNIFORM_DATA_SIZE = 16 * sizeof(float);
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+TriangleRenderer::TriangleRenderer(QVulkanWindow *w, bool msaa)
+ : m_window(w)
+{
+ if (msaa) {
+ const QVector<int> counts = w->supportedSampleCounts();
+ qDebug() << "Supported sample counts:" << counts;
+ for (int s = 16; s >= 4; s /= 2) {
+ if (counts.contains(s)) {
+ qDebug("Requesting sample count %d", s);
+ m_window->setSampleCount(s);
+ break;
+ }
+ }
+ }
+}
+
+VkShaderModule TriangleRenderer::createShader(const QString &name)
+{
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to read shader %s", qPrintable(name));
+ return VK_NULL_HANDLE;
+ }
+ QByteArray blob = file.readAll();
+ file.close();
+
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkShaderModule shaderModule;
+ VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return VK_NULL_HANDLE;
+ }
+
+ return shaderModule;
+}
+
+void TriangleRenderer::initResources()
+{
+ qDebug("initResources");
+
+ VkDevice dev = m_window->device();
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev);
+
+ // Prepare the vertex and uniform data. The vertex data will never
+ // change so one buffer is sufficient regardless of the value of
+ // QVulkanWindow::CONCURRENT_FRAME_COUNT. Uniform data is changing per
+ // frame however so active frames have to have a dedicated copy.
+
+ // Use just one memory allocation and one buffer. We will then specify the
+ // appropriate offsets for uniform buffers in the VkDescriptorBufferInfo.
+ // Have to watch out for
+ // VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment, though.
+
+ // The uniform buffer is not strictly required in this example, we could
+ // have used push constants as well since our single matrix (64 bytes) fits
+ // into the spec mandated minimum limit of 128 bytes. However, once that
+ // limit is not sufficient, the per-frame buffers, as shown below, will
+ // become necessary.
+
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+ qDebug("uniform buffer offset alignment is %u", (uint) uniAlign);
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ // Our internal layout is vertex, uniform, uniform, ... with each uniform buffer start offset aligned to uniAlign.
+ const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign);
+ const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign);
+ bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_buf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_buf, &memReq);
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_buf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind buffer memory: %d", err);
+
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, memReq.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, vertexData, sizeof(vertexData));
+ QMatrix4x4 ident;
+ memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
+ memcpy(p + offset, ident.constData(), 16 * sizeof(float));
+ m_uniformBufInfo[i].buffer = m_buf;
+ m_uniformBufInfo[i].offset = offset;
+ m_uniformBufInfo[i].range = uniformAllocSize;
+ }
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 5 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32_SFLOAT,
+ 0
+ },
+ { // color
+ 1,
+ 0,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 2 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = 2;
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Set up descriptor set and its layout.
+ VkDescriptorPoolSize descPoolSizes = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uint32_t(concurrentFrameCount) };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = concurrentFrameCount;
+ descPoolInfo.poolSizeCount = 1;
+ descPoolInfo.pPoolSizes = &descPoolSizes;
+ err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBinding = {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ 1,
+ &layoutBinding
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_descPool,
+ 1,
+ &m_descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_descSet[i]);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ VkWriteDescriptorSet descWrite;
+ memset(&descWrite, 0, sizeof(descWrite));
+ descWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite.dstSet = m_descSet[i];
+ descWrite.descriptorCount = 1;
+ descWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descWrite.pBufferInfo = &m_uniformBufInfo[i];
+ m_devFuncs->vkUpdateDescriptorSets(dev, 1, &descWrite, 0, nullptr);
+ }
+
+ // Pipeline cache
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ // Pipeline layout
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_descSetLayout;
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ // Shaders
+ VkShaderModule vertShaderModule = createShader(QStringLiteral(":/color_vert.spv"));
+ VkShaderModule fragShaderModule = createShader(QStringLiteral(":/color_frag.spv"));
+
+ // Graphics pipeline
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ vertShaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ fragShaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ // The viewport and scissor will be set dynamically via vkCmdSetViewport/Scissor.
+ // This way the pipeline does not need to be touched when resizing the window.
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_NONE; // we want the back face as well
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ // Enable multisampling.
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ // no blend, write out all of rgba
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+
+ if (vertShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, vertShaderModule, nullptr);
+ if (fragShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr);
+}
+
+void TriangleRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+
+ // Projection matrix
+ m_proj = m_window->clipCorrectionMatrix(); // adjust for Vulkan-OpenGL clip space differences
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void TriangleRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void TriangleRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+
+ VkDevice dev = m_window->device();
+
+ if (m_pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_pipeline, nullptr);
+ m_pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_pipelineLayout, nullptr);
+ m_pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr);
+ m_descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr);
+ m_descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_buf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr);
+ m_buf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+}
+
+void TriangleRenderer::startNextFrame()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ VkClearColorValue clearColor = { 0, 0, 0, 1 };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[3];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearValues[2].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = m_window->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem, m_uniformBufInfo[m_window->currentFrame()].offset,
+ UNIFORM_DATA_SIZE, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ QMatrix4x4 m = m_proj;
+ m.rotate(m_rotation, 0, 1, 0);
+ memcpy(p, m.constData(), 16 * sizeof(float));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Not exactly a real animation system, just advance on every frame for now.
+ m_rotation += 1.0f;
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1,
+ &m_descSet[m_window->currentFrame()], 0, nullptr);
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset);
+
+ VkViewport viewport;
+ viewport.x = viewport.y = 0;
+ viewport.width = sz.width();
+ viewport.height = sz.height();
+ viewport.minDepth = 0;
+ viewport.maxDepth = 1;
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor;
+ scissor.offset.x = scissor.offset.y = 0;
+ scissor.extent.width = viewport.width;
+ scissor.extent.height = viewport.height;
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ m_devFuncs->vkCmdDraw(cb, 3, 1, 0, 0);
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
diff --git a/examples/vulkan/shared/trianglerenderer.h b/examples/vulkan/shared/trianglerenderer.h
new file mode 100644
index 0000000000..9a33291a95
--- /dev/null
+++ b/examples/vulkan/shared/trianglerenderer.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+
+class TriangleRenderer : public QVulkanWindowRenderer
+{
+public:
+ TriangleRenderer(QVulkanWindow *w, bool msaa = false);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+protected:
+ VkShaderModule createShader(const QString &name);
+
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_buf = VK_NULL_HANDLE;
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkDescriptorPool m_descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout m_descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline m_pipeline = VK_NULL_HANDLE;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0.0f;
+};
diff --git a/examples/vulkan/vulkan.pro b/examples/vulkan/vulkan.pro
new file mode 100644
index 0000000000..920762cb9e
--- /dev/null
+++ b/examples/vulkan/vulkan.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+
+SUBDIRS = hellovulkanwindow \
+ hellovulkantriangle \
+ hellovulkantexture
+
+qtHaveModule(widgets) {
+ SUBDIRS += hellovulkanwidget
+ qtHaveModule(concurrent): SUBDIRS += hellovulkancubes
+}
diff --git a/examples/widgets/animation/animatedtiles/main.cpp b/examples/widgets/animation/animatedtiles/main.cpp
index 0511fe8162..8edd64e482 100644
--- a/examples/widgets/animation/animatedtiles/main.cpp
+++ b/examples/widgets/animation/animatedtiles/main.cpp
@@ -48,8 +48,9 @@
**
****************************************************************************/
-#include <QtWidgets>
+#include <QtWidgets/QtWidgets>
#include <QtCore/qmath.h>
+#include <QtCore/qrandom.h>
#include <QtCore/qstate.h>
class Pixmap : public QObject, public QGraphicsPixmapItem
@@ -202,8 +203,8 @@ int main(int argc, char **argv)
// Random
randomState->assignProperty(item, "pos",
- QPointF(-250 + qrand() % 500,
- -250 + qrand() % 500));
+ QPointF(-250 + QRandomGenerator::global()->bounded(500),
+ -250 + QRandomGenerator::global()->bounded(500)));
// Tiled
tiledState->assignProperty(item, "pos",
@@ -235,25 +236,25 @@ int main(int argc, char **argv)
anim->setEasingCurve(QEasingCurve::InOutBack);
group->addAnimation(anim);
}
- QAbstractTransition *trans = rootState->addTransition(ellipseButton, SIGNAL(pressed()), ellipseState);
+ QAbstractTransition *trans = rootState->addTransition(ellipseButton, &Button::pressed, ellipseState);
trans->addAnimation(group);
- trans = rootState->addTransition(figure8Button, SIGNAL(pressed()), figure8State);
+ trans = rootState->addTransition(figure8Button, &Button::pressed, figure8State);
trans->addAnimation(group);
- trans = rootState->addTransition(randomButton, SIGNAL(pressed()), randomState);
+ trans = rootState->addTransition(randomButton, &Button::pressed, randomState);
trans->addAnimation(group);
- trans = rootState->addTransition(tiledButton, SIGNAL(pressed()), tiledState);
+ trans = rootState->addTransition(tiledButton, &Button::pressed, tiledState);
trans->addAnimation(group);
- trans = rootState->addTransition(centeredButton, SIGNAL(pressed()), centeredState);
+ trans = rootState->addTransition(centeredButton, &Button::pressed, centeredState);
trans->addAnimation(group);
QTimer timer;
timer.start(125);
timer.setSingleShot(true);
- trans = rootState->addTransition(&timer, SIGNAL(timeout()), ellipseState);
+ trans = rootState->addTransition(&timer, &QTimer::timeout, ellipseState);
trans->addAnimation(group);
states.start();
diff --git a/examples/widgets/animation/animation.pro b/examples/widgets/animation/animation.pro
index a13f8bb65a..19b79caf15 100644
--- a/examples/widgets/animation/animation.pro
+++ b/examples/widgets/animation/animation.pro
@@ -2,7 +2,6 @@ TEMPLATE = \
subdirs
SUBDIRS += \
animatedtiles \
- appchooser \
easing \
moveblocks \
states \
diff --git a/examples/widgets/animation/appchooser/accessories-dictionary.png b/examples/widgets/animation/appchooser/accessories-dictionary.png
deleted file mode 100644
index e9bd55d918..0000000000
--- a/examples/widgets/animation/appchooser/accessories-dictionary.png
+++ /dev/null
Binary files differ
diff --git a/examples/widgets/animation/appchooser/akregator.png b/examples/widgets/animation/appchooser/akregator.png
deleted file mode 100644
index a086f45ab6..0000000000
--- a/examples/widgets/animation/appchooser/akregator.png
+++ /dev/null
Binary files differ
diff --git a/examples/widgets/animation/appchooser/appchooser.pro b/examples/widgets/animation/appchooser/appchooser.pro
deleted file mode 100644
index 674e623b2d..0000000000
--- a/examples/widgets/animation/appchooser/appchooser.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-QT += widgets
-
-SOURCES = main.cpp
-RESOURCES = appchooser.qrc
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/widgets/animation/appchooser
-INSTALLS += target
diff --git a/examples/widgets/animation/appchooser/appchooser.qrc b/examples/widgets/animation/appchooser/appchooser.qrc
deleted file mode 100644
index 28a3e1c4c1..0000000000
--- a/examples/widgets/animation/appchooser/appchooser.qrc
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
- <file>accessories-dictionary.png</file>
- <file>akregator.png</file>
- <file>digikam.png</file>
- <file>k3b.png</file>
-</qresource>
-</RCC>
diff --git a/examples/widgets/animation/appchooser/digikam.png b/examples/widgets/animation/appchooser/digikam.png
deleted file mode 100644
index 9de9fb2f80..0000000000
--- a/examples/widgets/animation/appchooser/digikam.png
+++ /dev/null
Binary files differ
diff --git a/examples/widgets/animation/appchooser/k3b.png b/examples/widgets/animation/appchooser/k3b.png
deleted file mode 100644
index bbcafcfba1..0000000000
--- a/examples/widgets/animation/appchooser/k3b.png
+++ /dev/null
Binary files differ
diff --git a/examples/widgets/animation/appchooser/main.cpp b/examples/widgets/animation/appchooser/main.cpp
deleted file mode 100644
index 71c869f6a2..0000000000
--- a/examples/widgets/animation/appchooser/main.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module 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$
-**
-****************************************************************************/
-
-#include <QtCore>
-#include <QtWidgets>
-
-
-class Pixmap : public QGraphicsWidget
-{
- Q_OBJECT
-
-public:
- Pixmap(const QPixmap &pix, QGraphicsItem *parent = 0)
- : QGraphicsWidget(parent), orig(pix), p(pix)
- {
- }
-
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
- {
- painter->drawPixmap(QPointF(), p);
- }
-
- void mousePressEvent(QGraphicsSceneMouseEvent *) override
- {
- emit clicked();
- }
-
- void setGeometry(const QRectF &rect) override
- {
- QGraphicsWidget::setGeometry(rect);
-
- if (rect.size().width() > orig.size().width())
- p = orig.scaled(rect.size().toSize());
- else
- p = orig;
- }
-
-Q_SIGNALS:
- void clicked();
-
-private:
- QPixmap orig;
- QPixmap p;
-};
-
-class GraphicsView : public QGraphicsView
-{
- Q_OBJECT
-public:
- GraphicsView(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent)
- {
- }
-
- void resizeEvent(QResizeEvent *) override
- {
- fitInView(sceneRect(), Qt::KeepAspectRatio);
- }
-};
-
-
-void createStates(const QObjectList &objects,
- const QRect &selectedRect, QState *parent)
-{
- for (int i = 0; i < objects.size(); ++i) {
- QState *state = new QState(parent);
- state->assignProperty(objects.at(i), "geometry", selectedRect);
- parent->addTransition(objects.at(i), SIGNAL(clicked()), state);
- }
-}
-
-void createAnimations(const QObjectList &objects, QStateMachine *machine)
-{
- for (int i=0; i<objects.size(); ++i)
- machine->addDefaultAnimation(new QPropertyAnimation(objects.at(i), "geometry"));
-}
-
-int main(int argc, char **argv)
-{
- Q_INIT_RESOURCE(appchooser);
-
- QApplication app(argc, argv);
-
- Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png"));
- Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png"));
- Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png"));
- Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png"));
-
- p1->setObjectName("p1");
- p2->setObjectName("p2");
- p3->setObjectName("p3");
- p4->setObjectName("p4");
-
- p1->setGeometry(QRectF( 0.0, 0.0, 64.0, 64.0));
- p2->setGeometry(QRectF(236.0, 0.0, 64.0, 64.0));
- p3->setGeometry(QRectF(236.0, 236.0, 64.0, 64.0));
- p4->setGeometry(QRectF( 0.0, 236.0, 64.0, 64.0));
-
- QGraphicsScene scene(0, 0, 300, 300);
- scene.setBackgroundBrush(Qt::white);
- scene.addItem(p1);
- scene.addItem(p2);
- scene.addItem(p3);
- scene.addItem(p4);
-
- GraphicsView window(&scene);
- window.setFrameStyle(0);
- window.setAlignment(Qt::AlignLeft | Qt::AlignTop);
- window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QState::RestoreProperties);
-
- QState *group = new QState(&machine);
- group->setObjectName("group");
-
- QRect selectedRect(86, 86, 128, 128);
-
- QState *idleState = new QState(group);
- group->setInitialState(idleState);
-
- QObjectList objects;
- objects << p1 << p2 << p3 << p4;
- createStates(objects, selectedRect, group);
- createAnimations(objects, &machine);
-
- machine.setInitialState(group);
- machine.start();
-
- window.resize(300, 300);
- window.show();
-
- return app.exec();
-}
-
-#include "main.moc"
diff --git a/examples/widgets/animation/easing/easing.pro b/examples/widgets/animation/easing/easing.pro
index 498180c0bb..097e232c2f 100644
--- a/examples/widgets/animation/easing/easing.pro
+++ b/examples/widgets/animation/easing/easing.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(listwidget))
HEADERS = window.h \
animation.h
diff --git a/examples/widgets/animation/easing/images/qt-logo.png b/examples/widgets/animation/easing/images/qt-logo.png
index 6b72d5fb72..d10bd0bdf9 100644
--- a/examples/widgets/animation/easing/images/qt-logo.png
+++ b/examples/widgets/animation/easing/images/qt-logo.png
Binary files differ
diff --git a/examples/widgets/animation/moveblocks/main.cpp b/examples/widgets/animation/moveblocks/main.cpp
index a9b95808a5..6d17696108 100644
--- a/examples/widgets/animation/moveblocks/main.cpp
+++ b/examples/widgets/animation/moveblocks/main.cpp
@@ -125,7 +125,7 @@ public:
void onEntry(QEvent *) override
{
int n;
- while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex)
+ while ((n = QRandomGenerator::global()->bounded(m_stateCount) + 1) == m_lastIndex)
{ }
m_lastIndex = n;
machine()->postEvent(new StateSwitchEvent(n));
@@ -323,8 +323,6 @@ int main(int argc, char **argv)
window.resize(300, 300);
window.show();
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
-
return app.exec();
}
diff --git a/examples/widgets/animation/stickman/lifecycle.cpp b/examples/widgets/animation/stickman/lifecycle.cpp
index 253af22b2d..dbe9a299b4 100644
--- a/examples/widgets/animation/stickman/lifecycle.cpp
+++ b/examples/widgets/animation/stickman/lifecycle.cpp
@@ -91,13 +91,12 @@ public:
: QEventTransition(this, QEvent::Timer)
{
setTargetState(target);
- qsrand((uint)QDateTime::currentSecsSinceEpoch());
startTimer(1000);
}
bool eventTest(QEvent *e) override
{
- return QEventTransition::eventTest(e) && ((qrand() % 50) == 0);
+ return QEventTransition::eventTest(e) && QRandomGenerator::global()->bounded(50) == 0;
}
};
//! [4]
diff --git a/examples/widgets/animation/stickman/stickman.cpp b/examples/widgets/animation/stickman/stickman.cpp
index 7a4629c4d2..b7a2d87ada 100644
--- a/examples/widgets/animation/stickman/stickman.cpp
+++ b/examples/widgets/animation/stickman/stickman.cpp
@@ -53,13 +53,7 @@
#include <QPainter>
#include <QTimer>
-
-#define _USE_MATH_DEFINES
-#include <math.h>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include <qmath.h>
static const qreal Coords[NodeCount * 2] = {
0.0, -150.0, // head, #0
@@ -300,7 +294,7 @@ void StickMan::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidge
QPointF dist = node2->pos() - node1->pos();
qreal sinAngle = dist.x() / sqrt(pow(dist.x(), 2) + pow(dist.y(), 2));
- qreal angle = asin(sinAngle) * 180.0 / M_PI;
+ qreal angle = qRadiansToDegrees(asin(sinAngle));
QPointF headPos = node1->pos();
painter->translate(headPos);
diff --git a/examples/widgets/animation/sub-attaq/main.cpp b/examples/widgets/animation/sub-attaq/main.cpp
index f65ca7be18..9b28d8c40f 100644
--- a/examples/widgets/animation/sub-attaq/main.cpp
+++ b/examples/widgets/animation/sub-attaq/main.cpp
@@ -57,8 +57,6 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
Q_INIT_RESOURCE(subattaq);
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
-
MainWindow w;
w.show();
diff --git a/examples/widgets/animation/sub-attaq/states.cpp b/examples/widgets/animation/sub-attaq/states.cpp
index 21cff048e7..e19704db7b 100644
--- a/examples/widgets/animation/sub-attaq/states.cpp
+++ b/examples/widgets/animation/sub-attaq/states.cpp
@@ -64,6 +64,7 @@
#include <QtCore/QStateMachine>
#include <QtWidgets/QKeyEventTransition>
#include <QtCore/QFinalState>
+#include <QtCore/QRandomGenerator>
PlayState::PlayState(GraphicsScene *scene, QState *parent)
: QState(parent),
@@ -193,12 +194,12 @@ void LevelState::initializeLevel()
for (int j = 0; j < subContent.second; ++j ) {
SubMarine *sub = new SubMarine(submarineDesc.type, submarineDesc.name, submarineDesc.points);
scene->addItem(sub);
- int random = (qrand() % 15 + 1);
+ int random = QRandomGenerator::global()->bounded(15) + 1;
qreal x = random == 13 || random == 5 ? 0 : scene->width() - sub->size().width();
- qreal y = scene->height() -(qrand() % 150 + 1) - sub->size().height();
+ qreal y = scene->height() -(QRandomGenerator::global()->bounded(150) + 1) - sub->size().height();
sub->setPos(x,y);
sub->setCurrentDirection(x == 0 ? SubMarine::Right : SubMarine::Left);
- sub->setCurrentSpeed(qrand() % 3 + 1);
+ sub->setCurrentSpeed(QRandomGenerator::global()->bounded(3) + 1);
}
}
}
diff --git a/examples/widgets/animation/sub-attaq/submarine_p.h b/examples/widgets/animation/sub-attaq/submarine_p.h
index b8d5532962..698b4b494f 100644
--- a/examples/widgets/animation/sub-attaq/submarine_p.h
+++ b/examples/widgets/animation/sub-attaq/submarine_p.h
@@ -69,6 +69,7 @@
//Qt
#include <QtCore/QPropertyAnimation>
+#include <QtCore/QRandomGenerator>
#include <QtWidgets/QGraphicsScene>
//This state is describing when the boat is moving right
@@ -88,8 +89,8 @@ public:
protected slots:
void onAnimationMovementValueChanged(const QVariant &)
{
- if (qrand() % 200 + 1 == 3)
- submarine->launchTorpedo(qrand() % 3 + 1);
+ if (QRandomGenerator::global()->bounded(200) + 1 == 3)
+ submarine->launchTorpedo(QRandomGenerator::global()->bounded(3) + 1);
}
protected:
diff --git a/examples/widgets/desktop/screenshot/screenshot.pro b/examples/widgets/desktop/screenshot/screenshot.pro
index d179833cbd..37108503de 100644
--- a/examples/widgets/desktop/screenshot/screenshot.pro
+++ b/examples/widgets/desktop/screenshot/screenshot.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = screenshot.h
SOURCES = main.cpp \
diff --git a/examples/widgets/desktop/systray/systray.pro b/examples/widgets/desktop/systray/systray.pro
index 1d4fdc7843..e0708ea832 100644
--- a/examples/widgets/desktop/systray/systray.pro
+++ b/examples/widgets/desktop/systray/systray.pro
@@ -4,6 +4,7 @@ SOURCES = main.cpp \
RESOURCES = systray.qrc
QT += widgets
+requires(qtConfig(combobox))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/desktop/systray
diff --git a/examples/widgets/dialogs/configdialog/configdialog.cpp b/examples/widgets/dialogs/configdialog/configdialog.cpp
deleted file mode 100644
index 5a0fb1c3bc..0000000000
--- a/examples/widgets/dialogs/configdialog/configdialog.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples 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$
-**
-****************************************************************************/
-
-#include <QtWidgets>
-
-#include "configdialog.h"
-#include "pages.h"
-
-ConfigDialog::ConfigDialog()
-{
- contentsWidget = new QListWidget;
- contentsWidget->setViewMode(QListView::IconMode);
- contentsWidget->setIconSize(QSize(96, 84));
- contentsWidget->setMovement(QListView::Static);
- contentsWidget->setMaximumWidth(128);
- contentsWidget->setSpacing(12);
-
- pagesWidget = new QStackedWidget;
- pagesWidget->addWidget(new ConfigurationPage);
- pagesWidget->addWidget(new UpdatePage);
- pagesWidget->addWidget(new QueryPage);
-
- QPushButton *closeButton = new QPushButton(tr("Close"));
-
- createIcons();
- contentsWidget->setCurrentRow(0);
-
- connect(closeButton, &QAbstractButton::clicked, this, &QWidget::close);
-
- QHBoxLayout *horizontalLayout = new QHBoxLayout;
- horizontalLayout->addWidget(contentsWidget);
- horizontalLayout->addWidget(pagesWidget, 1);
-
- QHBoxLayout *buttonsLayout = new QHBoxLayout;
- buttonsLayout->addStretch(1);
- buttonsLayout->addWidget(closeButton);
-
- QVBoxLayout *mainLayout = new QVBoxLayout;
- mainLayout->addLayout(horizontalLayout);
- mainLayout->addStretch(1);
- mainLayout->addSpacing(12);
- mainLayout->addLayout(buttonsLayout);
- setLayout(mainLayout);
-
- setWindowTitle(tr("Config Dialog"));
-}
-
-void ConfigDialog::createIcons()
-{
- QListWidgetItem *configButton = new QListWidgetItem(contentsWidget);
- configButton->setIcon(QIcon(":/images/config.png"));
- configButton->setText(tr("Configuration"));
- configButton->setTextAlignment(Qt::AlignHCenter);
- configButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
-
- QListWidgetItem *updateButton = new QListWidgetItem(contentsWidget);
- updateButton->setIcon(QIcon(":/images/update.png"));
- updateButton->setText(tr("Update"));
- updateButton->setTextAlignment(Qt::AlignHCenter);
- updateButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
-
- QListWidgetItem *queryButton = new QListWidgetItem(contentsWidget);
- queryButton->setIcon(QIcon(":/images/query.png"));
- queryButton->setText(tr("Query"));
- queryButton->setTextAlignment(Qt::AlignHCenter);
- queryButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
-
- connect(contentsWidget, &QListWidget::currentItemChanged, this, &ConfigDialog::changePage);
-}
-
-void ConfigDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous)
-{
- if (!current)
- current = previous;
-
- pagesWidget->setCurrentIndex(contentsWidget->row(current));
-}
diff --git a/examples/widgets/dialogs/configdialog/configdialog.pro b/examples/widgets/dialogs/configdialog/configdialog.pro
deleted file mode 100644
index 8ba55becad..0000000000
--- a/examples/widgets/dialogs/configdialog/configdialog.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-QT += widgets
-
-HEADERS = configdialog.h \
- pages.h
-SOURCES = configdialog.cpp \
- main.cpp \
- pages.cpp
-RESOURCES += configdialog.qrc
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/widgets/dialogs/configdialog
-INSTALLS += target
diff --git a/examples/widgets/dialogs/configdialog/configdialog.qrc b/examples/widgets/dialogs/configdialog/configdialog.qrc
deleted file mode 100644
index 31d0d49666..0000000000
--- a/examples/widgets/dialogs/configdialog/configdialog.qrc
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
- <file>images/config.png</file>
- <file>images/query.png</file>
- <file>images/update.png</file>
-</qresource>
-</RCC>
diff --git a/examples/widgets/dialogs/configdialog/images/config.png b/examples/widgets/dialogs/configdialog/images/config.png
deleted file mode 100644
index 5c14d5f470..0000000000
--- a/examples/widgets/dialogs/configdialog/images/config.png
+++ /dev/null
Binary files differ
diff --git a/examples/widgets/dialogs/configdialog/images/query.png b/examples/widgets/dialogs/configdialog/images/query.png
deleted file mode 100644
index ea9e291eeb..0000000000
--- a/examples/widgets/dialogs/configdialog/images/query.png
+++ /dev/null
Binary files differ
diff --git a/examples/widgets/dialogs/configdialog/images/update.png b/examples/widgets/dialogs/configdialog/images/update.png
deleted file mode 100644
index 3cb8ba6c77..0000000000
--- a/examples/widgets/dialogs/configdialog/images/update.png
+++ /dev/null
Binary files differ
diff --git a/examples/widgets/dialogs/configdialog/pages.cpp b/examples/widgets/dialogs/configdialog/pages.cpp
deleted file mode 100644
index 0c7762f029..0000000000
--- a/examples/widgets/dialogs/configdialog/pages.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples 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$
-**
-****************************************************************************/
-
-#include <QtWidgets>
-
-#include "pages.h"
-
-ConfigurationPage::ConfigurationPage(QWidget *parent)
- : QWidget(parent)
-{
- QGroupBox *configGroup = new QGroupBox(tr("Server configuration"));
-
- QLabel *serverLabel = new QLabel(tr("Server:"));
- QComboBox *serverCombo = new QComboBox;
- serverCombo->addItem(tr("Qt (Australia)"));
- serverCombo->addItem(tr("Qt (Germany)"));
- serverCombo->addItem(tr("Qt (Norway)"));
- serverCombo->addItem(tr("Qt (People's Republic of China)"));
- serverCombo->addItem(tr("Qt (USA)"));
-
- QHBoxLayout *serverLayout = new QHBoxLayout;
- serverLayout->addWidget(serverLabel);
- serverLayout->addWidget(serverCombo);
-
- QVBoxLayout *configLayout = new QVBoxLayout;
- configLayout->addLayout(serverLayout);
- configGroup->setLayout(configLayout);
-
- QVBoxLayout *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(configGroup);
- mainLayout->addStretch(1);
- setLayout(mainLayout);
-}
-
-UpdatePage::UpdatePage(QWidget *parent)
- : QWidget(parent)
-{
- QGroupBox *updateGroup = new QGroupBox(tr("Package selection"));
- QCheckBox *systemCheckBox = new QCheckBox(tr("Update system"));
- QCheckBox *appsCheckBox = new QCheckBox(tr("Update applications"));
- QCheckBox *docsCheckBox = new QCheckBox(tr("Update documentation"));
-
- QGroupBox *packageGroup = new QGroupBox(tr("Existing packages"));
-
- QListWidget *packageList = new QListWidget;
- QListWidgetItem *qtItem = new QListWidgetItem(packageList);
- qtItem->setText(tr("Qt"));
- QListWidgetItem *qsaItem = new QListWidgetItem(packageList);
- qsaItem->setText(tr("QSA"));
- QListWidgetItem *teamBuilderItem = new QListWidgetItem(packageList);
- teamBuilderItem->setText(tr("Teambuilder"));
-
- QPushButton *startUpdateButton = new QPushButton(tr("Start update"));
-
- QVBoxLayout *updateLayout = new QVBoxLayout;
- updateLayout->addWidget(systemCheckBox);
- updateLayout->addWidget(appsCheckBox);
- updateLayout->addWidget(docsCheckBox);
- updateGroup->setLayout(updateLayout);
-
- QVBoxLayout *packageLayout = new QVBoxLayout;
- packageLayout->addWidget(packageList);
- packageGroup->setLayout(packageLayout);
-
- QVBoxLayout *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(updateGroup);
- mainLayout->addWidget(packageGroup);
- mainLayout->addSpacing(12);
- mainLayout->addWidget(startUpdateButton);
- mainLayout->addStretch(1);
- setLayout(mainLayout);
-}
-
-QueryPage::QueryPage(QWidget *parent)
- : QWidget(parent)
-{
- QGroupBox *packagesGroup = new QGroupBox(tr("Look for packages"));
-
- QLabel *nameLabel = new QLabel(tr("Name:"));
- QLineEdit *nameEdit = new QLineEdit;
-
- QLabel *dateLabel = new QLabel(tr("Released after:"));
- QDateTimeEdit *dateEdit = new QDateTimeEdit(QDate::currentDate());
-
- QCheckBox *releasesCheckBox = new QCheckBox(tr("Releases"));
- QCheckBox *upgradesCheckBox = new QCheckBox(tr("Upgrades"));
-
- QSpinBox *hitsSpinBox = new QSpinBox;
- hitsSpinBox->setPrefix(tr("Return up to "));
- hitsSpinBox->setSuffix(tr(" results"));
- hitsSpinBox->setSpecialValueText(tr("Return only the first result"));
- hitsSpinBox->setMinimum(1);
- hitsSpinBox->setMaximum(100);
- hitsSpinBox->setSingleStep(10);
-
- QPushButton *startQueryButton = new QPushButton(tr("Start query"));
-
- QGridLayout *packagesLayout = new QGridLayout;
- packagesLayout->addWidget(nameLabel, 0, 0);
- packagesLayout->addWidget(nameEdit, 0, 1);
- packagesLayout->addWidget(dateLabel, 1, 0);
- packagesLayout->addWidget(dateEdit, 1, 1);
- packagesLayout->addWidget(releasesCheckBox, 2, 0);
- packagesLayout->addWidget(upgradesCheckBox, 3, 0);
- packagesLayout->addWidget(hitsSpinBox, 4, 0, 1, 2);
- packagesGroup->setLayout(packagesLayout);
-
- QVBoxLayout *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(packagesGroup);
- mainLayout->addSpacing(12);
- mainLayout->addWidget(startQueryButton);
- mainLayout->addStretch(1);
- setLayout(mainLayout);
-}
diff --git a/examples/widgets/dialogs/dialogs.pro b/examples/widgets/dialogs/dialogs.pro
index 82e814dcb0..753308fc55 100644
--- a/examples/widgets/dialogs/dialogs.pro
+++ b/examples/widgets/dialogs/dialogs.pro
@@ -2,7 +2,6 @@ QT_FOR_CONFIG += widgets
TEMPLATE = subdirs
SUBDIRS = classwizard \
- configdialog \
extension \
findfiles \
licensewizard \
@@ -14,4 +13,3 @@ SUBDIRS = classwizard \
!qtConfig(wizard) {
SUBDIRS -= trivialwizard licensewizard classwizard
}
-wince: SUBDIRS += sipdialog
diff --git a/examples/widgets/dialogs/findfiles/findfiles.pro b/examples/widgets/dialogs/findfiles/findfiles.pro
index 2dd058ac5c..4fb77f0dd7 100644
--- a/examples/widgets/dialogs/findfiles/findfiles.pro
+++ b/examples/widgets/dialogs/findfiles/findfiles.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = window.h
SOURCES = main.cpp \
diff --git a/examples/widgets/dialogs/findfiles/window.cpp b/examples/widgets/dialogs/findfiles/window.cpp
index f2ce853d99..1b16cdcd35 100644
--- a/examples/widgets/dialogs/findfiles/window.cpp
+++ b/examples/widgets/dialogs/findfiles/window.cpp
@@ -74,6 +74,7 @@ static inline void openFile(const QString &fileName)
Window::Window(QWidget *parent)
: QWidget(parent)
{
+ setWindowTitle(tr("Find Files"));
QPushButton *browseButton = new QPushButton(tr("&Browse..."), this);
connect(browseButton, &QAbstractButton::clicked, this, &Window::browse);
findButton = new QPushButton(tr("&Find"), this);
@@ -92,9 +93,7 @@ Window::Window(QWidget *parent)
filesFoundLabel = new QLabel;
createFilesTable();
-//! [0]
-//! [1]
QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->addWidget(new QLabel(tr("Named:")), 0, 0);
mainLayout->addWidget(fileComboBox, 0, 1, 1, 2);
@@ -106,12 +105,13 @@ Window::Window(QWidget *parent)
mainLayout->addWidget(filesTable, 3, 0, 1, 3);
mainLayout->addWidget(filesFoundLabel, 4, 0, 1, 2);
mainLayout->addWidget(findButton, 4, 2);
+//! [0]
- setWindowTitle(tr("Find Files"));
- const QRect screenGeometry = QApplication::desktop()->screenGeometry(this);
- resize(screenGeometry.width() / 2, screenGeometry.height() / 3);
-}
//! [1]
+ connect(new QShortcut(QKeySequence::Quit, this), &QShortcut::activated,
+ qApp, &QApplication::quit);
+//! [1]
+}
//! [2]
void Window::browse()
@@ -133,21 +133,7 @@ static void updateComboBox(QComboBox *comboBox)
comboBox->addItem(comboBox->currentText());
}
-//! [13]
-
-static void findRecursion(const QString &path, const QString &pattern, QStringList *result)
-{
- QDir currentDir(path);
- const QString prefix = path + QLatin1Char('/');
- foreach (const QString &match, currentDir.entryList(QStringList(pattern), QDir::Files | QDir::NoSymLinks))
- result->append(prefix + match);
- foreach (const QString &dir, currentDir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot))
- findRecursion(prefix + dir, pattern, result);
-}
-
-//! [13]
//! [3]
-
void Window::find()
{
filesTable->setRowCount(0);
@@ -155,6 +141,7 @@ void Window::find()
QString fileName = fileComboBox->currentText();
QString text = textComboBox->currentText();
QString path = QDir::cleanPath(directoryComboBox->currentText());
+ currentDir = QDir(path);
//! [3]
updateComboBox(fileComboBox);
@@ -162,12 +149,16 @@ void Window::find()
updateComboBox(directoryComboBox);
//! [4]
-
- currentDir = QDir(path);
+ QStringList filter;
+ if (!fileName.isEmpty())
+ filter << fileName;
+ QDirIterator it(path, filter, QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
QStringList files;
- findRecursion(path, fileName.isEmpty() ? QStringLiteral("*") : fileName, &files);
+ while (it.hasNext())
+ files << it.next();
if (!text.isEmpty())
files = findFiles(files, text);
+ files.sort();
showFiles(files);
}
//! [4]
@@ -225,20 +216,18 @@ QStringList Window::findFiles(const QStringList &files, const QString &text)
//! [7]
//! [8]
-void Window::showFiles(const QStringList &files)
+void Window::showFiles(const QStringList &paths)
{
- for (int i = 0; i < files.size(); ++i) {
- const QString &fileName = files.at(i);
- const QString toolTip = QDir::toNativeSeparators(fileName);
- const QString relativePath = QDir::toNativeSeparators(currentDir.relativeFilePath(fileName));
- const qint64 size = QFileInfo(fileName).size();
+ for (const QString &filePath : paths) {
+ const QString toolTip = QDir::toNativeSeparators(filePath);
+ const QString relativePath = QDir::toNativeSeparators(currentDir.relativeFilePath(filePath));
+ const qint64 size = QFileInfo(filePath).size();
QTableWidgetItem *fileNameItem = new QTableWidgetItem(relativePath);
- fileNameItem->setData(absoluteFileNameRole, QVariant(fileName));
+ fileNameItem->setData(absoluteFileNameRole, QVariant(filePath));
fileNameItem->setToolTip(toolTip);
fileNameItem->setFlags(fileNameItem->flags() ^ Qt::ItemIsEditable);
- QTableWidgetItem *sizeItem = new QTableWidgetItem(tr("%1 KB")
- .arg(int((size + 1023) / 1024)));
- sizeItem->setData(absoluteFileNameRole, QVariant(fileName));
+ QTableWidgetItem *sizeItem = new QTableWidgetItem(QLocale().formattedDataSize(size));
+ sizeItem->setData(absoluteFileNameRole, QVariant(filePath));
sizeItem->setToolTip(toolTip);
sizeItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
sizeItem->setFlags(sizeItem->flags() ^ Qt::ItemIsEditable);
@@ -248,7 +237,7 @@ void Window::showFiles(const QStringList &files)
filesTable->setItem(row, 0, fileNameItem);
filesTable->setItem(row, 1, sizeItem);
}
- filesFoundLabel->setText(tr("%n file(s) found (Double click on a file to open it)", 0, files.size()));
+ filesFoundLabel->setText(tr("%n file(s) found (Double click on a file to open it)", 0, paths.size()));
filesFoundLabel->setWordWrap(true);
}
//! [8]
diff --git a/examples/widgets/dialogs/findfiles/window.h b/examples/widgets/dialogs/findfiles/window.h
index fe217381e2..949df704bb 100644
--- a/examples/widgets/dialogs/findfiles/window.h
+++ b/examples/widgets/dialogs/findfiles/window.h
@@ -79,7 +79,7 @@ private slots:
private:
QStringList findFiles(const QStringList &files, const QString &text);
- void showFiles(const QStringList &files);
+ void showFiles(const QStringList &paths);
QComboBox *createComboBox(const QString &text = QString());
void createFilesTable();
diff --git a/examples/widgets/dialogs/standarddialogs/standarddialogs.pro b/examples/widgets/dialogs/standarddialogs/standarddialogs.pro
index d2e9e19771..95396db022 100644
--- a/examples/widgets/dialogs/standarddialogs/standarddialogs.pro
+++ b/examples/widgets/dialogs/standarddialogs/standarddialogs.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = dialog.h
SOURCES = dialog.cpp \
diff --git a/examples/widgets/dialogs/tabdialog/tabdialog.pro b/examples/widgets/dialogs/tabdialog/tabdialog.pro
index 8a686b4f5c..00f1815ca8 100644
--- a/examples/widgets/dialogs/tabdialog/tabdialog.pro
+++ b/examples/widgets/dialogs/tabdialog/tabdialog.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(listwidget))
HEADERS = tabdialog.h
SOURCES = main.cpp \
diff --git a/examples/widgets/doc/images/addressbook-editdialog.png b/examples/widgets/doc/images/addressbook-editdialog.png
index fd41ee63f7..7434aa44ef 100644
--- a/examples/widgets/doc/images/addressbook-editdialog.png
+++ b/examples/widgets/doc/images/addressbook-editdialog.png
Binary files differ
diff --git a/examples/widgets/doc/images/addressbook-example.png b/examples/widgets/doc/images/addressbook-example.png
index b743c166da..eebe97a718 100644
--- a/examples/widgets/doc/images/addressbook-example.png
+++ b/examples/widgets/doc/images/addressbook-example.png
Binary files differ
diff --git a/examples/widgets/doc/images/addressbook-newaddresstab.png b/examples/widgets/doc/images/addressbook-newaddresstab.png
index ff215a4b20..6b60ee08e9 100644
--- a/examples/widgets/doc/images/addressbook-newaddresstab.png
+++ b/examples/widgets/doc/images/addressbook-newaddresstab.png
Binary files differ
diff --git a/examples/widgets/doc/images/graphicssimpleanchorlayout-example.png b/examples/widgets/doc/images/graphicssimpleanchorlayout-example.png
index 543670e05c..e4bed44edf 100644
--- a/examples/widgets/doc/images/graphicssimpleanchorlayout-example.png
+++ b/examples/widgets/doc/images/graphicssimpleanchorlayout-example.png
Binary files differ
diff --git a/examples/widgets/doc/images/itemviews-editabletreemodel.png b/examples/widgets/doc/images/itemviews-editabletreemodel.png
index a151ea857f..ff6cf637a1 100644
--- a/examples/widgets/doc/images/itemviews-editabletreemodel.png
+++ b/examples/widgets/doc/images/itemviews-editabletreemodel.png
Binary files differ
diff --git a/examples/widgets/doc/images/notepad.png b/examples/widgets/doc/images/notepad.png
new file mode 100644
index 0000000000..40d13269b9
--- /dev/null
+++ b/examples/widgets/doc/images/notepad.png
Binary files differ
diff --git a/examples/widgets/doc/images/notepad1.png b/examples/widgets/doc/images/notepad1.png
new file mode 100644
index 0000000000..40d13269b9
--- /dev/null
+++ b/examples/widgets/doc/images/notepad1.png
Binary files differ
diff --git a/examples/widgets/doc/images/notepad2.png b/examples/widgets/doc/images/notepad2.png
new file mode 100644
index 0000000000..9cec1f9a58
--- /dev/null
+++ b/examples/widgets/doc/images/notepad2.png
Binary files differ
diff --git a/examples/widgets/doc/images/notepad3.png b/examples/widgets/doc/images/notepad3.png
new file mode 100644
index 0000000000..426861ab06
--- /dev/null
+++ b/examples/widgets/doc/images/notepad3.png
Binary files differ
diff --git a/examples/widgets/doc/images/notepad4.png b/examples/widgets/doc/images/notepad4.png
new file mode 100644
index 0000000000..fc08eab204
--- /dev/null
+++ b/examples/widgets/doc/images/notepad4.png
Binary files differ
diff --git a/examples/widgets/doc/images/notepad_menu.png b/examples/widgets/doc/images/notepad_menu.png
new file mode 100644
index 0000000000..2dd771111a
--- /dev/null
+++ b/examples/widgets/doc/images/notepad_menu.png
Binary files differ
diff --git a/examples/widgets/doc/images/stylesheet-pagefold.png b/examples/widgets/doc/images/stylesheet-pagefold.png
index 5ccb4edbc9..d1358f326b 100644
--- a/examples/widgets/doc/images/stylesheet-pagefold.png
+++ b/examples/widgets/doc/images/stylesheet-pagefold.png
Binary files differ
diff --git a/examples/widgets/doc/src/addressbook.qdoc b/examples/widgets/doc/src/addressbook.qdoc
index b9bcae21aa..1fa0bfa9d4 100644
--- a/examples/widgets/doc/src/addressbook.qdoc
+++ b/examples/widgets/doc/src/addressbook.qdoc
@@ -60,8 +60,8 @@
the address book.
\c TableModel is a subclass of QAbstractTableModel that provides
- the standard model/view API to access data. It also holds a
- QList of \l{QPair}s corresponding to the contacts added.
+ the standard model/view API to access data. It holds a list of
+ added contacts.
However, this data is not all visible in a single tab. Instead,
QTableView is used to provide 9 different views of the same
data, according to the alphabet groups.
@@ -80,7 +80,7 @@
\section1 TableModel Class Definition
The \c TableModel class provides standard API to access data in
- its QList of \l{QPair}s by subclassing QAbstractTableModel. The
+ its list of contacts by subclassing QAbstractTableModel. The
basic functions that must be implemented in order to do so are:
\c rowCount(), \c columnCount(), \c data(), \c headerData().
For TableModel to be editable, it has to provide implementations
@@ -90,15 +90,14 @@
\snippet itemviews/addressbook/tablemodel.h 0
Two constructors are used, a default constructor which uses
- \c TableModel's own \c {QList<QPair<QString, QString>>} and one
- that takes \c {QList<QPair<QString, QString>} as an argument,
- for convenience.
+ \c TableModel's own \c {QList<Contact>} and one that takes
+ \c {QList<Contact>} as an argument, for convenience.
\section1 TableModel Class Implementation
We implement the two constructors as defined in the header file.
- The second constructor initializes the list of pairs in the
+ The second constructor initializes the list of contacts in the
model, with the parameter value.
\snippet itemviews/addressbook/tablemodel.cpp 0
@@ -117,7 +116,7 @@
The \c data() function returns either a \b Name or
\b {Address}, based on the contents of the model index
supplied. The row number stored in the model index is used to
- reference an item in the list of pairs. Selection is handled
+ reference an item in the list of contacts. Selection is handled
by the QItemSelectionModel, which will be explained with
\c AddressWidget.
@@ -164,12 +163,11 @@
use the editing features of the QTableView object, we enable
them here so that we can reuse the model in other programs.
- The last function in \c {TableModel}, \c getList() returns the
- QList<QPair<QString, QString>> object that holds all the
- contacts in the address book. We use this function later to
- obtain the list of contacts to check for existing entries, write
- the contacts to a file and read them back. Further explanation is
- given with \c AddressWidget.
+ The last function in \c {TableModel}, \c getContacts() returns the
+ QList<Contact> object that holds all the contacts in the address
+ book. We use this function later to obtain the list of contacts to
+ check for existing entries, write the contacts to a file and read
+ them back. Further explanation is given with \c AddressWidget.
\snippet itemviews/addressbook/tablemodel.cpp 8
@@ -222,11 +220,12 @@
The QItemSelectionModel class provides a
\l{QItemSelectionModel::selectionChanged()}{selectionChanged}
signal that is connected to \c{AddressWidget}'s
- \c selectionChanged() signal. This signal to signal connection
- is necessary to enable the \uicontrol{Edit Entry...} and
- \uicontrol{Remove Entry} actions in \c MainWindow's Tools menu. This
- connection is further explained in \c MainWindow's
- implementation.
+ \c selectionChanged() signal. We also connect
+ QTabWidget::currentChanged() signal to the lambda expression which
+ emits \c{AddressWidget}'s \c selectionChanged() as well. These
+ connections are necessary to enable the \uicontrol{Edit Entry...} and
+ \uicontrol{Remove Entry} actions in \c MainWindow's Tools menu.
+ It is further explained in \c MainWindow's implementation.
Each table view in the address book is added as a tab to the
QTabWidget with the relevant label, obtained from the QStringList
@@ -250,7 +249,7 @@
Basic validation is done in the second \c addEntry() function to
prevent duplicate entries in the address book. As mentioned with
\c TableModel, this is part of the reason why we require the
- getter method \c getList().
+ getter method \c getContacts().
\snippet itemviews/addressbook/addresswidget.cpp 3
@@ -292,7 +291,7 @@
The \c writeToFile() function is used to save a file containing
all the contacts in the address book. The file is saved in a
- custom \c{.dat} format. The contents of the QList of \l{QPair}s
+ custom \c{.dat} format. The contents of the list of contacts
are written to \c file using QDataStream. If the file cannot be
opened, a QMessageBox is displayed with the related error message.
@@ -301,7 +300,7 @@
The \c readFromFile() function loads a file containing all the
contacts in the address book, previously saved using
\c writeToFile(). QDataStream is used to read the contents of a
- \c{.dat} file into a list of pairs and each of these is added
+ \c{.dat} file into a list of contacts and each of these is added
using \c addEntry().
\snippet itemviews/addressbook/addresswidget.cpp 7
diff --git a/examples/widgets/doc/src/basiclayouts.qdoc b/examples/widgets/doc/src/basiclayouts.qdoc
index 01bcaa8c1a..e9d7cea21b 100644
--- a/examples/widgets/doc/src/basiclayouts.qdoc
+++ b/examples/widgets/doc/src/basiclayouts.qdoc
@@ -67,11 +67,11 @@
In the constructor, we first use the \c createMenu() function to
create and populate a menu bar and the \c createHorizontalGroupBox()
function to create a group box containing four buttons with a
- horizontal layout. Next we use the \c createGridGroupBox() function
+ horizontal layout. Next, we use the \c createGridGroupBox() function
to create a group box containing several line edits and a small text
editor which are displayed in a grid layout. Finally, we use the
\c createFormGroupBox() function to create a group box with
- three labels and three input fields: a line edit, a combo box and
+ three labels and three input fields: a line edit, a combo box, and
a spin box.
\snippet layouts/basiclayouts/dialog.cpp 1
@@ -111,7 +111,7 @@
\snippet layouts/basiclayouts/dialog.cpp 4
We use the QBoxLayout::addWidget() function to add the widgets to
- the end of layout. Each widget will get at least its minimum size
+ the end of the layout. Each widget will get at least its minimum size
and at most its maximum size. It is possible to specify a stretch
factor in the \l {QBoxLayout::addWidget()}{addWidget()} function,
and any excess space is shared according to these stretch
diff --git a/examples/widgets/doc/src/blurpicker.qdoc b/examples/widgets/doc/src/blurpicker.qdoc
index f12184e4c9..87f36389e7 100644
--- a/examples/widgets/doc/src/blurpicker.qdoc
+++ b/examples/widgets/doc/src/blurpicker.qdoc
@@ -32,4 +32,13 @@
\brief Demonstrates how to apply graphical effects on items in the view
\image blurpickereffect-example.png
+
+ The Blur Picker example displays a circle of application icons.
+ All icons are blurred, except the one on the bottom left side of
+ the screen, which is the one in focus.
+ Clicking anywhere on the left side of the screen moves the icon
+ circle clockwise to the next icon
+ Clicking on the right side advances the circle counterclockwise.
+
+ \sa QGraphicsBlurEffect
*/
diff --git a/examples/widgets/doc/src/calendarwidget.qdoc b/examples/widgets/doc/src/calendarwidget.qdoc
index eaf8f547da..c04fab1fc7 100644
--- a/examples/widgets/doc/src/calendarwidget.qdoc
+++ b/examples/widgets/doc/src/calendarwidget.qdoc
@@ -110,8 +110,8 @@
size hints of its contents widgets.
To ensure that the window isn't automatically resized every time
- we change a property of the QCalendarWidget (e.g., hiding the
- navigation bar, trhe vertical header, or the grid), we set the
+ we change a property of the QCalendarWidget (for example, hiding the
+ navigation bar, the vertical header, or the grid), we set the
minimum height of row 0 and the minimum width of column 0 to the
initial size of the QCalendarWidget.
@@ -126,8 +126,8 @@
the formatting specified by the user.
The \c createGeneralOptionsGroupBox() function is somewhat large
- and several widgets are set up the same way; we look at parts of
- its implementation here and skip the rest:
+ and several widgets are set up in the same way. We will look at
+ parts of its implementation here and skip the rest:
\snippet widgets/calendarwidget/window.cpp 10
\dots
@@ -146,7 +146,7 @@
\snippet widgets/calendarwidget/window.cpp 11
\dots
- After creating the widgets, we connect the signals and slots. We
+ After having created the widgets, we connect the signals and slots. We
connect the comboboxes to private slots of \c Window or to
public slots provided by QComboBox.
diff --git a/examples/widgets/doc/src/collidingmice-example.qdoc b/examples/widgets/doc/src/collidingmice-example.qdoc
index 02417ba521..535057bb6a 100644
--- a/examples/widgets/doc/src/collidingmice-example.qdoc
+++ b/examples/widgets/doc/src/collidingmice-example.qdoc
@@ -80,8 +80,7 @@
\snippet graphicsview/collidingmice/mouse.cpp 0
To calculate the various components of the mouse's color, we use
- the global qrand() function which is a thread-safe version of the
- standard C++ rand() function.
+ \l QRandomGenerator.
Then we call the \l {QGraphicsItem::setRotation()}{setRotation()} function
inherited from QGraphicsItem. Items live in their own local
@@ -178,12 +177,7 @@
\snippet graphicsview/collidingmice/main.cpp 0
- First, we create an application object and call the global
- qsrand() function to specify the seed used to generate a new
- random number sequence of pseudo random integers with the
- previously mentioned qrand() function.
-
- Then it is time to create the scene:
+ First, we create an application object and create the scene:
\snippet graphicsview/collidingmice/main.cpp 1
diff --git a/examples/widgets/doc/src/customsortfiltermodel.qdoc b/examples/widgets/doc/src/customsortfiltermodel.qdoc
index 0eb6560e10..6eab846e89 100644
--- a/examples/widgets/doc/src/customsortfiltermodel.qdoc
+++ b/examples/widgets/doc/src/customsortfiltermodel.qdoc
@@ -75,7 +75,7 @@
QSortFilterProxyModel's default implementations of functions are
written so that they call the equivalent functions in the relevant
source model. This simple proxying mechanism may need to be
- overridden for source models with more complex behavior; in this
+ overridden for source models with more complex behavior. In this
example we derive from the QSortFilterProxyModel class to ensure
that our filter can recognize a valid range of dates, and to
control the sorting behavior.
@@ -170,7 +170,7 @@
We implement two private slots, \c textFilterChanged() and \c
dateFilterChanged(), to respond to the user changing the filter
- pattern, case sensitivity or any of the dates. In addition, we
+ pattern, case sensitivity, or any of the dates. In addition, we
implement a public \c setSourceModel() convenience function to set
up the model/ view relation.
@@ -197,7 +197,7 @@
\snippet itemviews/customsortfiltermodel/window.cpp 1
The QTreeView class provides a default model/view implementation
- of a tree view; our view implements a tree representation of items
+ of a tree view. Our view implements a tree representation of items
in the application's source model.
\snippet itemviews/customsortfiltermodel/window.cpp 2
diff --git a/examples/widgets/doc/src/dragdroprobot.qdoc b/examples/widgets/doc/src/dragdroprobot.qdoc
index ac221ec5f9..f74b898e1b 100644
--- a/examples/widgets/doc/src/dragdroprobot.qdoc
+++ b/examples/widgets/doc/src/dragdroprobot.qdoc
@@ -257,7 +257,7 @@
\snippet graphicsview/dragdroprobot/coloritem.cpp 0
\c ColorItem's constructor assigns an opaque random color to its color
- member by making use of qrand(). For improved usability, it assigns a
+ member by making use of \l QRandomGenerator. For improved usability, it assigns a
tooltip that provides a useful hint to the user, and it also sets a
suitable cursor. This ensures that the cursor will chance to
Qt::OpenHandCursor when the mouse pointer hovers over the item.
diff --git a/examples/widgets/doc/src/draggabletext.qdoc b/examples/widgets/doc/src/draggabletext.qdoc
index c4a694028b..97b2f036bd 100644
--- a/examples/widgets/doc/src/draggabletext.qdoc
+++ b/examples/widgets/doc/src/draggabletext.qdoc
@@ -28,6 +28,7 @@
/*!
\example draganddrop/draggabletext
\title Draggable Text Example
+ \brief Illustrates how to drag and drop text between widgets
\brief The Draggable Text example shows how to drag and drop textual data between widgets
in the same application, and between different applications.
diff --git a/examples/widgets/doc/src/easing.qdoc b/examples/widgets/doc/src/easing.qdoc
index 3a9727d393..807dd72e93 100644
--- a/examples/widgets/doc/src/easing.qdoc
+++ b/examples/widgets/doc/src/easing.qdoc
@@ -34,4 +34,7 @@
\image easing-example.png
+ See \l QEasingCurve for a detailed description on how to use the class's
+ functionalities.
+
*/
diff --git a/examples/widgets/doc/src/elasticnodes.qdoc b/examples/widgets/doc/src/elasticnodes.qdoc
index 09ac891b24..65e1195121 100644
--- a/examples/widgets/doc/src/elasticnodes.qdoc
+++ b/examples/widgets/doc/src/elasticnodes.qdoc
@@ -424,9 +424,8 @@
\section1 The main() Function
In contrast to the complexity of the rest of this example, the \c main()
- function is very simple: We create a QApplication instance, seed the
- randomizer using qsrand(), and then create and show an instance of \c
- GraphWidget. Because all nodes in the grid are moved initially, the \c
- GraphWidget timer will start immediately after control has returned to the
- event loop.
+ function is very simple: We create a QApplication instance, then create and
+ show an instance of \c GraphWidget. Because all nodes in the grid are moved
+ initially, the \c GraphWidget timer will start immediately after control
+ has returned to the event loop.
*/
diff --git a/examples/widgets/doc/src/findfiles.qdoc b/examples/widgets/doc/src/findfiles.qdoc
index b8363dc698..a2eb326519 100644
--- a/examples/widgets/doc/src/findfiles.qdoc
+++ b/examples/widgets/doc/src/findfiles.qdoc
@@ -74,19 +74,23 @@
\snippet dialogs/findfiles/window.cpp 0
- We create the application's buttons using the private \c
- createButton() function. Then we create the comboboxes associated
- with the search specifications, using the private \c
- createComboBox() function. We also create the application's labels
- before we use the private \c createFilesTable() function to create
- the table displaying the search results.
+ We create the widgets to build up the UI, and we add them to a main layout
+ using QGridLayout. We have, however, put the \c Find and \c Quit buttons
+ and a stretchable space in a separate \l QHBoxLayout first, to make the
+ buttons appear in the \c Window widget's bottom right corner.
+
+ Alternatively, we could have used Qt Designer to construct a UI file,
+ and \l {uic} to generate this code.
\snippet dialogs/findfiles/window.cpp 1
- Then we add all the widgets to a main layout using QGridLayout. We
- have, however, put the \c Find and \c Quit buttons and a
- stretchable space in a separate QHBoxLayout first, to make the
- buttons appear in the \c Window widget's bottom right corner.
+ We did not create a \l QMenuBar with a \uicontrol Quit menu item; but we
+ would still like to have a keyboard shortcut for quitting. Since we
+ construct a \l QShortcut with \l QKeySequence::Quit, and connect it to
+ \l QApplication::quit(), on most platforms it will be possible to press
+ Control-Q to quit (or whichever standard Quit key is configured on that platform).
+ (On \macos, this is redundant, because every application gets a
+ \uicontrol Quit menu item automatically; but it helps to make the application portable.)
\snippet dialogs/findfiles/window.cpp 2
@@ -122,18 +126,16 @@
We use the directory's path to create a QDir; the QDir class
provides access to directory structures and their contents.
- \snippet dialogs/findfiles/window.cpp 13
-
- We recursively create a list of the files (contained in the newl
- created QDir) that match the specified file name.
+ We use QDirIterator to iterate over the files that match the
+ specified file name and build a QStringList of paths.
Then we search through all the files in the list, using the private
- \c findFiles() function, eliminating the ones that don't contain
- the specified text. And finally, we display the results using the
- private \c showFiles() function.
+ \c findFiles() function, eliminating the ones that don't contain the
+ specified text. We sort them (because QDirIterator did not). And finally,
+ we display the results using the private \c showFiles() function.
If the user didn't specify any text, there is no reason to search
- through the files, and we display the results immediately.
+ through the files, so we sort and display the results immediately.
\image findfiles_progress_dialog.png Screenshot of the Progress Dialog
@@ -196,7 +198,8 @@
the \c find() slot. In the \c showFiles() function we run through
the provided list of file names, adding each relative file name to the
first column in the table widget and retrieving the file's size using
- QFileInfo for the second column. For later use, we set
+ QFileInfo for the second column. We use \l QLocale::formattedDataSize()
+ to format the file size in a human-readable form. For later use, we set
the absolute path as a data on the QTableWidget using the
the role absoluteFileNameRole defined to be Qt::UserRole + 1.
diff --git a/examples/widgets/doc/src/graphicsview-anchorlayout.qdoc b/examples/widgets/doc/src/graphicsview-anchorlayout.qdoc
index 95717340d1..bd27a0dc4f 100644
--- a/examples/widgets/doc/src/graphicsview-anchorlayout.qdoc
+++ b/examples/widgets/doc/src/graphicsview-anchorlayout.qdoc
@@ -35,4 +35,47 @@
class.
\image graphicsanchorlayout-example.png
+
+ The basic steps of this example are:
+ \list
+ \li Create a QGraphicsScene
+ \li Create widgets
+ \li Create a QGraphicsAnchorLayout
+ \li Create a QGraphicsWidget
+ \li Add vertical and horizontal anchors between the widgets
+ \li View the scene with a QGraphicsView object
+ \endlist
+
+ \section1 Creating a QGraphicsScene
+
+ \quotefromfile graphicsview/anchorlayout/main.cpp
+ \skipto QGraphicsScene
+ \printuntil setSceneRect
+
+ \section1 Creating Widgets
+
+ \skipto QGraphicsProxyWidget
+ \printuntil *g
+
+ \section1 Creating a Layout
+
+ \skipto QGraphicsAnchorLayout
+ \printuntil l->setSpacing
+
+ \section1 Creating a QGraphicsWidget
+
+ \skipto QGraphicsWidget
+ \printuntil setLayout(l)
+
+ \section1 Adding Anchors
+
+ \skipto vertical
+ \printuntil l->addAnchor(f, Qt::AnchorRight
+
+ \section1 Viewing the Scene with QGraphicsView
+
+ \skipto scene.addItem
+ \printuntil view.show
+
+ \sa {Simple Anchor Layout Example}
*/
diff --git a/examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc b/examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc
index 866dac442b..fd0427fdc0 100644
--- a/examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc
+++ b/examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc
@@ -35,4 +35,50 @@
QGraphicsAnchorLayout class.
\image graphicssimpleanchorlayout-example.png
+
+ The example starts by creating a QGraphicsScene (\c scene), 3 widgets
+ (\c a, \c b, and \c c), and a QGraphicsAnchorlayout (\c layout).
+
+ \quotefromfile graphicsview/simpleanchorlayout/main.cpp
+ \skipto QGraphicsScene
+ \printuntil QGraphicsAnchorLayout
+
+ First it anchors the top left corner of item \c a to the top left
+ corner of \c layout. This can be done in two steps:
+
+ \skipto layout->addAnchor(a
+ \printto adding
+
+ Or in one step:
+
+ \skipuntil [adding a corner anchor]
+ \printline layout->addCornerAnchors(a, Qt::T
+
+ Then the right anchor of \c a is anchored to the left anchor of
+ \c b, and the top of item \c b is anchored to the bottom of \c a.
+
+ \skipuntil [adding anchors]
+ \printto adding anchors
+
+ Place a third widget \c c under widget \c b:
+
+ \skipuntil third widget
+ \printline AnchorBottom
+
+ Items \c b and \c c are anchored to each other horizontally:
+
+ \skipto Qt::Horizontal
+ \printline Qt::Horizontal
+
+ Item c is anchored to the bottom right point of \c layout
+
+ \skipuntil corner of the layout
+ \printline Qt::BottomRightCorner
+
+ Finally, QGraphicsWidget \c w is displayed in QGraphicsView \c view.
+
+ \skipto QGraphicsWidget
+ \printuntil app.exec()
+
+ \sa {Anchor Layout Example}
*/
diff --git a/examples/widgets/doc/src/painterpaths.qdoc b/examples/widgets/doc/src/painterpaths.qdoc
index 2cc5ff410a..bd821ac1bf 100644
--- a/examples/widgets/doc/src/painterpaths.qdoc
+++ b/examples/widgets/doc/src/painterpaths.qdoc
@@ -98,14 +98,9 @@
\section1 Window Class Implementation
- In the implementation of the \c Window class we first declare the
- constant \c Pi with six significant figures:
-
- \snippet painting/painterpaths/window.cpp 0
-
- In the constructor, we then define the various painter paths and
- create corresponding \c RenderArea widgets which will render the
- graphical shapes:
+ In the \c Window constructor, we define the various painter paths
+ and create corresponding \c RenderArea widgets which will render
+ the graphical shapes:
\snippet painting/painterpaths/window.cpp 1
diff --git a/examples/widgets/doc/src/stardelegate.qdoc b/examples/widgets/doc/src/stardelegate.qdoc
index dcc7080456..44d17662ca 100644
--- a/examples/widgets/doc/src/stardelegate.qdoc
+++ b/examples/widgets/doc/src/stardelegate.qdoc
@@ -37,7 +37,7 @@
When displaying data in a QListView, QTableView, or QTreeView,
the individual items are drawn by a
\l{Delegate Classes}{delegate}. Also, when the user starts
- editing an item (e.g., by double-clicking the item), the delegate
+ editing an item (for example, by double-clicking the item), the delegate
provides an editor widget that is placed on top of the item while
editing takes place.
@@ -96,9 +96,9 @@
QItemDelegate paint it for us. This ensures that the \c
StarDelegate can handle the most common data types.
- In the case where the item is a \c StarRating, we draw the
- background if the item is selected, and we draw the item using \c
- StarRating::paint(), which we will review later.
+ If the item is a \c StarRating, we draw the background if the
+ item is selected, and we draw the item using \c StarRating::paint(),
+ which we will review later.
\c{StartRating}s can be stored in a QVariant thanks to the
Q_DECLARE_METATYPE() macro appearing in \c starrating.h. More on
@@ -133,8 +133,8 @@
We simply call \c setStarRating() on the editor.
The \l{QAbstractItemDelegate::}{setModelData()} function is
- called when editing is finished, to commit data from the editor
- to the model:
+ called to commit data from the editor to the model when editing
+ is finished:
\snippet itemviews/stardelegate/stardelegate.cpp 4
@@ -210,7 +210,7 @@
current rating, and \c myMaxStarCount stores the highest possible
rating (typically 5).
- The Q_DECLARE_METATYPE() macro makes the type \c StarRating known
+ The \c Q_DECLARE_METATYPE() macro makes the type \c StarRating known
to QVariant, making it possible to store \c StarRating values in
QVariant.
@@ -283,7 +283,7 @@
\list
\li It is possible to open editors programmatically by calling
QAbstractItemView::edit(), instead of relying on edit
- triggers. This could be use to support other edit triggers
+ triggers. This could be used to support other edit triggers
than those offered by the QAbstractItemView::EditTrigger enum.
For example, in the Star Delegate example, hovering over an
item with the mouse might make sense as a way to pop up an
diff --git a/examples/widgets/doc/src/stylesheet.qdoc b/examples/widgets/doc/src/stylesheet.qdoc
index 0016836f0d..a86b697059 100644
--- a/examples/widgets/doc/src/stylesheet.qdoc
+++ b/examples/widgets/doc/src/stylesheet.qdoc
@@ -33,5 +33,56 @@
\borderedimage stylesheet-pagefold.png
\caption Screen Shot of the Pagefold style sheet
+
+ The Style Sheet example shows how widgets can be styled using Qt Style Sheets.
+ You can open the style editor by selecting \uicontrol File > \uicontrol Edit Style Sheet,
+ to select an existing style sheet or design your own style and load it.
+
+ The Style Sheet example consists of 2 classes:
+ \list
+ \li \c MainWindow
+ \li \c StyleSheetEditor
+ \endlist
+
+
+ \section1 MainWindow Class
+
+ \c MainWindow inherits QWidget, and is the application's main window defined in
+ \c mainwindow.ui. The style of \c MainWindow can be modified with \l StyleSheetEditor.
+
+
+ \section1 StyleSheetEditor Class
+
+ \c StyleSheetEditor enables you to open an editor where you can load an existing style sheet.
+ It is also possible to define a new stylesheet and load it. Its layout is defined in
+ \c stylesheeteditor.ui.
+
+ \quotefromfile widgets/stylesheet/stylesheeteditor.cpp
+ \skipto on_styleCombo_activated
+ \printline on_styleCombo_activated
+
+ Sets the specified \a styleName and grays the \c applyButton.
+
+ \skipto on_styleSheetCombo_activated
+ \printline on_styleSheetCombo_activated
+
+ Loads the stylesheet from \c styleSheetName.
+
+ \skipto on_styleTextEdit_textChanged()
+ \printline on_styleTextEdit_textChanged()
+
+ Enables the \c applyButton when the text in the buffer has changed.
+
+ \skipto on_applyButton_clicked()
+ \printline on_applyButton_clicked()
+
+ Sets the stylesheet properties in \l qApp and disables the \c applyButton.
+
+ \skipto loadStyleSheet(const QString &sheetName)
+ \printline loadStyleSheet(const QString &sheetName)
+
+ Loads the specified \a sheetName, and sets its properties in
+ \l qApp.
+
*/
diff --git a/examples/widgets/doc/src/tablet.qdoc b/examples/widgets/doc/src/tablet.qdoc
index 88fdefa68f..2b11020c07 100644
--- a/examples/widgets/doc/src/tablet.qdoc
+++ b/examples/widgets/doc/src/tablet.qdoc
@@ -206,8 +206,7 @@
\snippet widgets/tablet/tabletcanvas.cpp 0
- In the constructor we initialize our class variables. We need
- to draw the background of our pixmap, as the default is gray.
+ In the constructor we initialize most of our class variables.
Here is the implementation of \c saveImage():
@@ -247,7 +246,15 @@
\snippet widgets/tablet/tabletcanvas.cpp 4
- We simply draw the pixmap to the top left of the widget.
+ The first time Qt calls paintEvent(), m_pixmap is default-constructed, so
+ QPixmap::isNull() returns \c true. Now that we know which screen we will be
+ rendering to, we can create a pixmap with the appropriate resolution.
+ The size of the pixmap with which we fill the window depends on the screen
+ resolution, as the example does not support zoom; and it may be that one
+ screen is \l {High DPI Displays}{high DPI} while another is not. We need to
+ draw the background too, as the default is gray.
+
+ After that, we simply draw the pixmap to the top left of the widget.
Here is the implementation of \c paintPixmap():
diff --git a/examples/widgets/doc/src/validators.qdoc b/examples/widgets/doc/src/validators.qdoc
index f3f4dc5e63..bbb2e5f7b6 100644
--- a/examples/widgets/doc/src/validators.qdoc
+++ b/examples/widgets/doc/src/validators.qdoc
@@ -31,4 +31,6 @@
\ingroup examples-widgets
\brief The Validators example shows the signal emission behavior of input
validators.
+
+ \borderedimage validators.png
*/
diff --git a/examples/widgets/draganddrop/draggableicons/dragwidget.h b/examples/widgets/draganddrop/draggableicons/dragwidget.h
index 18be074b61..98e623a5e3 100644
--- a/examples/widgets/draganddrop/draggableicons/dragwidget.h
+++ b/examples/widgets/draganddrop/draggableicons/dragwidget.h
@@ -62,7 +62,7 @@ QT_END_NAMESPACE
class DragWidget : public QFrame
{
public:
- DragWidget(QWidget *parent = 0);
+ explicit DragWidget(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
diff --git a/examples/widgets/draganddrop/draggabletext/dragwidget.cpp b/examples/widgets/draganddrop/draggabletext/dragwidget.cpp
index fb169b953b..2135ba2ef9 100644
--- a/examples/widgets/draganddrop/draggabletext/dragwidget.cpp
+++ b/examples/widgets/draganddrop/draggabletext/dragwidget.cpp
@@ -123,7 +123,7 @@ void DragWidget::dropEvent(QDropEvent *event)
hotSpot.setY(hotSpotPos.last().toInt());
}
- foreach (const QString &piece, pieces) {
+ for (const QString &piece : pieces) {
QLabel *newLabel = createDragLabel(piece, this);
newLabel->move(position - hotSpot);
newLabel->show();
@@ -141,7 +141,7 @@ void DragWidget::dropEvent(QDropEvent *event)
} else {
event->ignore();
}
- foreach (QWidget *widget, findChildren<QWidget *>()) {
+ for (QWidget *widget : findChildren<QWidget *>()) {
if (!widget->isVisible())
widget->deleteLater();
}
diff --git a/examples/widgets/draganddrop/draggabletext/dragwidget.h b/examples/widgets/draganddrop/draggabletext/dragwidget.h
index 24d1f6f5c7..38abb0ceb8 100644
--- a/examples/widgets/draganddrop/draggabletext/dragwidget.h
+++ b/examples/widgets/draganddrop/draggabletext/dragwidget.h
@@ -61,7 +61,7 @@ QT_END_NAMESPACE
class DragWidget : public QWidget
{
public:
- DragWidget(QWidget *parent = 0);
+ explicit DragWidget(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
diff --git a/examples/widgets/draganddrop/dropsite/droparea.h b/examples/widgets/draganddrop/dropsite/droparea.h
index 5b6e209dfa..ab1de8ea44 100644
--- a/examples/widgets/draganddrop/dropsite/droparea.h
+++ b/examples/widgets/draganddrop/dropsite/droparea.h
@@ -63,13 +63,13 @@ class DropArea : public QLabel
Q_OBJECT
public:
- DropArea(QWidget *parent = 0);
+ explicit DropArea(QWidget *parent = nullptr);
public slots:
void clear();
signals:
- void changed(const QMimeData *mimeData = 0);
+ void changed(const QMimeData *mimeData = nullptr);
//! [DropArea header part1]
//! [DropArea header part2]
diff --git a/examples/widgets/draganddrop/dropsite/dropsite.pro b/examples/widgets/draganddrop/dropsite/dropsite.pro
index 606b0c266d..41455a46dc 100644
--- a/examples/widgets/draganddrop/dropsite/dropsite.pro
+++ b/examples/widgets/draganddrop/dropsite/dropsite.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(tablewidget))
HEADERS = droparea.h \
dropsitewindow.h
diff --git a/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp b/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp
index dc865ac171..28a42ee614 100644
--- a/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp
+++ b/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp
@@ -88,8 +88,8 @@ DropSiteWindow::DropSiteWindow()
buttonBox->addButton(clearButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
- connect(quitButton, &QAbstractButton::pressed, this, &QWidget::close);
- connect(clearButton, &QAbstractButton::pressed, dropArea, &DropArea::clear);
+ connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close);
+ connect(clearButton, &QAbstractButton::clicked, dropArea, &DropArea::clear);
//! [constructor part4]
//! [constructor part5]
@@ -113,7 +113,7 @@ void DropSiteWindow::updateFormatsTable(const QMimeData *mimeData)
//! [updateFormatsTable() part1]
//! [updateFormatsTable() part2]
- foreach (QString format, mimeData->formats()) {
+ for (const QString &format : mimeData->formats()) {
QTableWidgetItem *formatItem = new QTableWidgetItem(format);
formatItem->setFlags(Qt::ItemIsEnabled);
formatItem->setTextAlignment(Qt::AlignTop | Qt::AlignLeft);
diff --git a/examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp b/examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp
index b185b2900d..451b53f623 100644
--- a/examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp
+++ b/examples/widgets/draganddrop/fridgemagnets/dragwidget.cpp
@@ -167,7 +167,7 @@ void DragWidget::dropEvent(QDropEvent *event)
QString::SkipEmptyParts);
QPoint position = event->pos();
- foreach (const QString &piece, pieces) {
+ for (const QString &piece : pieces) {
DragLabel *newLabel = new DragLabel(piece, this);
newLabel->move(position);
newLabel->show();
diff --git a/examples/widgets/draganddrop/fridgemagnets/dragwidget.h b/examples/widgets/draganddrop/fridgemagnets/dragwidget.h
index 104e500134..ff513a33d8 100644
--- a/examples/widgets/draganddrop/fridgemagnets/dragwidget.h
+++ b/examples/widgets/draganddrop/fridgemagnets/dragwidget.h
@@ -62,7 +62,7 @@ QT_END_NAMESPACE
class DragWidget : public QWidget
{
public:
- DragWidget(QWidget *parent = 0);
+ explicit DragWidget(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
diff --git a/examples/widgets/draganddrop/puzzle/main.cpp b/examples/widgets/draganddrop/puzzle/main.cpp
index 0bf65a89c5..d013bf078d 100644
--- a/examples/widgets/draganddrop/puzzle/main.cpp
+++ b/examples/widgets/draganddrop/puzzle/main.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QApplication>
-
#include "mainwindow.h"
+#include <QApplication>
+
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(puzzle);
diff --git a/examples/widgets/draganddrop/puzzle/mainwindow.cpp b/examples/widgets/draganddrop/puzzle/mainwindow.cpp
index 806133583a..98a7cd4265 100644
--- a/examples/widgets/draganddrop/puzzle/mainwindow.cpp
+++ b/examples/widgets/draganddrop/puzzle/mainwindow.cpp
@@ -67,12 +67,19 @@ MainWindow::MainWindow(QWidget *parent)
void MainWindow::openImage()
{
- const QString fileName =
- QFileDialog::getOpenFileName(this, tr("Open Image"), QString(),
- tr("Image Files (*.png *.jpg *.bmp)"));
-
- if (!fileName.isEmpty())
- loadImage(fileName);
+ const QString directory =
+ QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::homePath());
+ QFileDialog dialog(this, tr("Open Image"), directory);
+ dialog.setAcceptMode(QFileDialog::AcceptOpen);
+ dialog.setFileMode(QFileDialog::ExistingFile);
+ QStringList mimeTypeFilters;
+ for (const QByteArray &mimeTypeName : QImageReader::supportedMimeTypes())
+ mimeTypeFilters.append(mimeTypeName);
+ mimeTypeFilters.sort();
+ dialog.setMimeTypeFilters(mimeTypeFilters);
+ dialog.selectMimeTypeFilter("image/jpeg");
+ if (dialog.exec() == QDialog::Accepted)
+ loadImage(dialog.selectedFiles().constFirst());
}
void MainWindow::loadImage(const QString &fileName)
@@ -101,8 +108,8 @@ void MainWindow::setCompleted()
void MainWindow::setupPuzzle()
{
int size = qMin(puzzleImage.width(), puzzleImage.height());
- puzzleImage = puzzleImage.copy((puzzleImage.width() - size)/2,
- (puzzleImage.height() - size)/2, size, size).scaled(puzzleWidget->width(),
+ puzzleImage = puzzleImage.copy((puzzleImage.width() - size) / 2,
+ (puzzleImage.height() - size) / 2, size, size).scaled(puzzleWidget->width(),
puzzleWidget->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
piecesList->clear();
@@ -115,10 +122,8 @@ void MainWindow::setupPuzzle()
}
}
- qsrand(QCursor::pos().x() ^ QCursor::pos().y());
-
for (int i = 0; i < piecesList->count(); ++i) {
- if (int(2.0*qrand()/(RAND_MAX+1.0)) == 1) {
+ if (QRandomGenerator::global()->bounded(2) == 1) {
QListWidgetItem *item = piecesList->takeItem(i);
piecesList->insertItem(0, item);
}
diff --git a/examples/widgets/draganddrop/puzzle/mainwindow.h b/examples/widgets/draganddrop/puzzle/mainwindow.h
index e43f52cab8..626612ebe8 100644
--- a/examples/widgets/draganddrop/puzzle/mainwindow.h
+++ b/examples/widgets/draganddrop/puzzle/mainwindow.h
@@ -51,8 +51,8 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
-#include <QPixmap>
#include <QMainWindow>
+#include <QPixmap>
class PiecesList;
class PuzzleWidget;
@@ -65,7 +65,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- MainWindow(QWidget *parent = 0);
+ explicit MainWindow(QWidget *parent = nullptr);
void loadImage(const QString &path);
public slots:
diff --git a/examples/widgets/draganddrop/puzzle/pieceslist.cpp b/examples/widgets/draganddrop/puzzle/pieceslist.cpp
index 30890ecf9b..7846d37ed2 100644
--- a/examples/widgets/draganddrop/puzzle/pieceslist.cpp
+++ b/examples/widgets/draganddrop/puzzle/pieceslist.cpp
@@ -101,7 +101,7 @@ void PiecesList::dropEvent(QDropEvent *event)
}
}
-void PiecesList::addPiece(QPixmap pixmap, QPoint location)
+void PiecesList::addPiece(const QPixmap &pixmap, const QPoint &location)
{
QListWidgetItem *pieceItem = new QListWidgetItem(this);
pieceItem->setIcon(QIcon(pixmap));
diff --git a/examples/widgets/draganddrop/puzzle/pieceslist.h b/examples/widgets/draganddrop/puzzle/pieceslist.h
index b67d2bdaf7..a508d17d72 100644
--- a/examples/widgets/draganddrop/puzzle/pieceslist.h
+++ b/examples/widgets/draganddrop/puzzle/pieceslist.h
@@ -58,8 +58,8 @@ class PiecesList : public QListWidget
Q_OBJECT
public:
- explicit PiecesList(int pieceSize, QWidget *parent = 0);
- void addPiece(QPixmap pixmap, QPoint location);
+ explicit PiecesList(int pieceSize, QWidget *parent = nullptr);
+ void addPiece(const QPixmap &pixmap, const QPoint &location);
static QString puzzleMimeType() { return QStringLiteral("image/x-puzzle-piece"); }
diff --git a/examples/widgets/draganddrop/puzzle/puzzle.pro b/examples/widgets/draganddrop/puzzle/puzzle.pro
index 97e7206682..c462ba1bb8 100644
--- a/examples/widgets/draganddrop/puzzle/puzzle.pro
+++ b/examples/widgets/draganddrop/puzzle/puzzle.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = mainwindow.h \
pieceslist.h \
diff --git a/examples/widgets/draganddrop/puzzle/puzzlewidget.cpp b/examples/widgets/draganddrop/puzzle/puzzlewidget.cpp
index 2093d7820c..72f2662bce 100644
--- a/examples/widgets/draganddrop/puzzle/puzzlewidget.cpp
+++ b/examples/widgets/draganddrop/puzzle/puzzlewidget.cpp
@@ -66,9 +66,7 @@ PuzzleWidget::PuzzleWidget(int imageSize, QWidget *parent)
void PuzzleWidget::clear()
{
- pieceLocations.clear();
- piecePixmaps.clear();
- pieceRects.clear();
+ pieces.clear();
highlightedRect = QRect();
inPlace = 0;
update();
@@ -95,7 +93,7 @@ void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event)
QRect updateRect = highlightedRect.united(targetSquare(event->pos()));
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())
- && pieceRects.indexOf(targetSquare(event->pos())) == -1) {
+ && findPiece(targetSquare(event->pos())) == -1) {
highlightedRect = targetSquare(event->pos());
event->setDropAction(Qt::MoveAction);
@@ -111,26 +109,23 @@ void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event)
void PuzzleWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())
- && pieceRects.indexOf(targetSquare(event->pos())) == -1) {
+ && findPiece(targetSquare(event->pos())) == -1) {
QByteArray pieceData = event->mimeData()->data(PiecesList::puzzleMimeType());
QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
- QRect square = targetSquare(event->pos());
- QPixmap pixmap;
- QPoint location;
- dataStream >> pixmap >> location;
+ Piece piece;
+ piece.rect = targetSquare(event->pos());
+ dataStream >> piece.pixmap >> piece.location;
- pieceLocations.append(location);
- piecePixmaps.append(pixmap);
- pieceRects.append(square);
+ pieces.append(piece);
highlightedRect = QRect();
- update(square);
+ update(piece.rect);
event->setDropAction(Qt::MoveAction);
event->accept();
- if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize())) {
+ if (piece.location == piece.rect.topLeft() / pieceSize()) {
inPlace++;
if (inPlace == 25)
emit puzzleCompleted();
@@ -141,21 +136,26 @@ void PuzzleWidget::dropEvent(QDropEvent *event)
}
}
+int PuzzleWidget::findPiece(const QRect &pieceRect) const
+{
+ for (int i = 0, size = pieces.size(); i < size; ++i) {
+ if (pieces.at(i).rect == pieceRect)
+ return i;
+ }
+ return -1;
+}
+
void PuzzleWidget::mousePressEvent(QMouseEvent *event)
{
QRect square = targetSquare(event->pos());
- int found = pieceRects.indexOf(square);
+ const int found = findPiece(square);
if (found == -1)
return;
- QPoint location = pieceLocations[found];
- QPixmap pixmap = piecePixmaps[found];
- pieceLocations.removeAt(found);
- piecePixmaps.removeAt(found);
- pieceRects.removeAt(found);
+ Piece piece = pieces.takeAt(found);
- if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize()))
+ if (piece.location == square.topLeft() / pieceSize())
inPlace--;
update(square);
@@ -163,7 +163,7 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
- dataStream << pixmap << location;
+ dataStream << piece.pixmap << piece.location;
QMimeData *mimeData = new QMimeData;
mimeData->setData(PiecesList::puzzleMimeType(), itemData);
@@ -171,23 +171,20 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(event->pos() - square.topLeft());
- drag->setPixmap(pixmap);
+ drag->setPixmap(piece.pixmap);
- if (!(drag->exec(Qt::MoveAction) == Qt::MoveAction)) {
- pieceLocations.insert(found, location);
- piecePixmaps.insert(found, pixmap);
- pieceRects.insert(found, square);
+ if (drag->exec(Qt::MoveAction) != Qt::MoveAction) {
+ pieces.insert(found, piece);
update(targetSquare(event->pos()));
- if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize()))
+ if (piece.location == square.topLeft() / pieceSize())
inPlace++;
}
}
void PuzzleWidget::paintEvent(QPaintEvent *event)
{
- QPainter painter;
- painter.begin(this);
+ QPainter painter(this);
painter.fillRect(event->rect(), Qt::white);
if (highlightedRect.isValid()) {
@@ -196,14 +193,14 @@ void PuzzleWidget::paintEvent(QPaintEvent *event)
painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1));
}
- for (int i = 0; i < pieceRects.size(); ++i)
- painter.drawPixmap(pieceRects[i], piecePixmaps[i]);
- painter.end();
+ for (const Piece &piece : pieces)
+ painter.drawPixmap(piece.rect, piece.pixmap);
}
const QRect PuzzleWidget::targetSquare(const QPoint &position) const
{
- return QRect(position.x()/pieceSize() * pieceSize(), position.y()/pieceSize() * pieceSize(), pieceSize(), pieceSize());
+ return QRect(position / pieceSize() * pieceSize(),
+ QSize(pieceSize(), pieceSize()));
}
int PuzzleWidget::pieceSize() const
diff --git a/examples/widgets/draganddrop/puzzle/puzzlewidget.h b/examples/widgets/draganddrop/puzzle/puzzlewidget.h
index 7dcb7dd497..40dd654af6 100644
--- a/examples/widgets/draganddrop/puzzle/puzzlewidget.h
+++ b/examples/widgets/draganddrop/puzzle/puzzlewidget.h
@@ -51,9 +51,9 @@
#ifndef PUZZLEWIDGET_H
#define PUZZLEWIDGET_H
-#include <QList>
#include <QPoint>
#include <QPixmap>
+#include <QVector>
#include <QWidget>
QT_BEGIN_NAMESPACE
@@ -67,7 +67,7 @@ class PuzzleWidget : public QWidget
Q_OBJECT
public:
- explicit PuzzleWidget(int imageSize, QWidget *parent = 0);
+ explicit PuzzleWidget(int imageSize, QWidget *parent = nullptr);
void clear();
int pieceSize() const;
@@ -85,11 +85,16 @@ protected:
void paintEvent(QPaintEvent *event) override;
private:
+ struct Piece {
+ QPixmap pixmap;
+ QRect rect;
+ QPoint location;
+ };
+
+ int findPiece(const QRect &pieceRect) const;
const QRect targetSquare(const QPoint &position) const;
- QList<QPixmap> piecePixmaps;
- QList<QRect> pieceRects;
- QList<QPoint> pieceLocations;
+ QVector<Piece> pieces;
QRect highlightedRect;
int inPlace;
int m_ImageSize;
diff --git a/examples/widgets/effects/blurpicker/blurpicker.cpp b/examples/widgets/effects/blurpicker/blurpicker.cpp
index 43823bed30..a00af2144a 100644
--- a/examples/widgets/effects/blurpicker/blurpicker.cpp
+++ b/examples/widgets/effects/blurpicker/blurpicker.cpp
@@ -52,13 +52,9 @@
#include <QtWidgets>
#include <QtCore/qmath.h>
-
+#include <qmath.h>
#include "blureffect.h"
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0), m_animation(this, "index")
{
setBackgroundBrush(QPixmap(":/images/background.jpg"));
@@ -84,9 +80,10 @@ void BlurPicker::setIndex(qreal index)
m_index = index;
qreal baseline = 0;
+ const qreal iconAngle = 2 * M_PI / m_icons.count();
for (int i = 0; i < m_icons.count(); ++i) {
QGraphicsItem *icon = m_icons[i];
- qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count();
+ qreal a = (i + m_index) * iconAngle;
qreal xs = 170 * qSin(a);
qreal ys = 100 * qCos(a);
QPointF pos(xs, ys);
diff --git a/examples/widgets/effects/effects.pro b/examples/widgets/effects/effects.pro
index 795e0508ac..05911979b9 100644
--- a/examples/widgets/effects/effects.pro
+++ b/examples/widgets/effects/effects.pro
@@ -2,5 +2,4 @@ TEMPLATE = \
subdirs
SUBDIRS = \
blurpicker \
- lighting \
fademessage
diff --git a/examples/widgets/effects/lighting/lighting.cpp b/examples/widgets/effects/lighting/lighting.cpp
deleted file mode 100644
index 68350f32b7..0000000000
--- a/examples/widgets/effects/lighting/lighting.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples 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$
-**
-****************************************************************************/
-
-#include "lighting.h"
-
-#include <QtWidgets>
-#include <QtCore/qmath.h>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0)
-{
- setScene(&m_scene);
-
- setupScene();
-
- QTimer *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), SLOT(animate()));
- timer->setInterval(30);
- timer->start();
-
- setRenderHint(QPainter::Antialiasing, true);
- setFrameStyle(QFrame::NoFrame);
-}
-
-void Lighting::setupScene()
-{
- m_scene.setSceneRect(-300, -200, 600, 460);
-
- QLinearGradient linearGrad(QPointF(-100, -100), QPointF(100, 100));
- linearGrad.setColorAt(0, QColor(255, 255, 255));
- linearGrad.setColorAt(1, QColor(192, 192, 255));
- setBackgroundBrush(linearGrad);
-
- QRadialGradient radialGrad(30, 30, 30);
- radialGrad.setColorAt(0, Qt::yellow);
- radialGrad.setColorAt(0.2, Qt::yellow);
- radialGrad.setColorAt(1, Qt::transparent);
- QPixmap pixmap(60, 60);
- pixmap.fill(Qt::transparent);
- QPainter painter(&pixmap);
- painter.setPen(Qt::NoPen);
- painter.setBrush(radialGrad);
- painter.drawEllipse(0, 0, 60, 60);
- painter.end();
-
- m_lightSource = m_scene.addPixmap(pixmap);
- m_lightSource->setZValue(2);
-
- for (int i = -2; i < 3; ++i)
- for (int j = -2; j < 3; ++j) {
- QAbstractGraphicsShapeItem *item;
- if ((i + j) & 1)
- item = new QGraphicsEllipseItem(0, 0, 50, 50);
- else
- item = new QGraphicsRectItem(0, 0, 50, 50);
-
- item->setPen(QPen(Qt::black, 1));
- item->setBrush(QBrush(Qt::white));
- QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
- effect->setBlurRadius(8);
- item->setGraphicsEffect(effect);
- item->setZValue(1);
- item->setPos(i * 80, j * 80);
- m_scene.addItem(item);
- m_items << item;
- }
-
-
-}
-
-void Lighting::animate()
-{
- angle += (M_PI / 30);
- qreal xs = 200 * qSin(angle) - 40 + 25;
- qreal ys = 200 * qCos(angle) - 40 + 25;
- m_lightSource->setPos(xs, ys);
-
- for (int i = 0; i < m_items.size(); ++i) {
- QGraphicsItem *item = m_items.at(i);
- Q_ASSERT(item);
- QGraphicsDropShadowEffect *effect = static_cast<QGraphicsDropShadowEffect *>(item->graphicsEffect());
- Q_ASSERT(effect);
-
- QPointF delta(item->x() - xs, item->y() - ys);
- effect->setOffset(delta.toPoint() / 30);
-
- qreal dx = delta.x();
- qreal dy = delta.y();
- qreal dd = qSqrt(dx * dx + dy * dy);
- QColor color = effect->color();
- color.setAlphaF(qBound(0.4, 1 - dd / 200.0, 0.7));
- effect->setColor(color);
- }
-
- m_scene.update();
-}
-
-void Lighting::resizeEvent(QResizeEvent * /* event */)
-{
-}
diff --git a/examples/widgets/effects/lighting/lighting.pro b/examples/widgets/effects/lighting/lighting.pro
deleted file mode 100644
index 0a3b397de5..0000000000
--- a/examples/widgets/effects/lighting/lighting.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-QT += widgets
-
-SOURCES += main.cpp lighting.cpp
-HEADERS += lighting.h
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/widgets/effects/lighting
-INSTALLS += target
diff --git a/examples/widgets/gestures/imagegestures/imagegestures.pro b/examples/widgets/gestures/imagegestures/imagegestures.pro
index 0d5b2f286c..9563e5fcc3 100644
--- a/examples/widgets/gestures/imagegestures/imagegestures.pro
+++ b/examples/widgets/gestures/imagegestures/imagegestures.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = imagewidget.h \
mainwidget.h
diff --git a/examples/widgets/graphicsview/boxes/boxes.pro b/examples/widgets/graphicsview/boxes/boxes.pro
index afdca816b1..601edd6883 100644
--- a/examples/widgets/graphicsview/boxes/boxes.pro
+++ b/examples/widgets/graphicsview/boxes/boxes.pro
@@ -1,4 +1,5 @@
QT += opengl widgets
+requires(qtConfig(combobox))
qtConfig(opengles.|angle|dynamicgl): error("This example requires Qt to be configured with -opengl desktop")
diff --git a/examples/widgets/graphicsview/boxes/glbuffers.cpp b/examples/widgets/graphicsview/boxes/glbuffers.cpp
index 1481292e76..851cd17796 100644
--- a/examples/widgets/graphicsview/boxes/glbuffers.cpp
+++ b/examples/widgets/graphicsview/boxes/glbuffers.cpp
@@ -50,11 +50,11 @@
#include "glbuffers.h"
#include <QtGui/qmatrix4x4.h>
-
+#include <QtCore/qmath.h>
void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
- const GLdouble ymax = zNear * tan(fovy * M_PI / 360.0);
+ const GLdouble ymax = zNear * tan(qDegreesToRadians(fovy) / 2.0);
const GLdouble ymin = -ymax;
const GLdouble xmin = ymin * aspect;
const GLdouble xmax = ymax * aspect;
diff --git a/examples/widgets/graphicsview/boxes/qtbox.cpp b/examples/widgets/graphicsview/boxes/qtbox.cpp
index 9a19985fac..3a184dd0b6 100644
--- a/examples/widgets/graphicsview/boxes/qtbox.cpp
+++ b/examples/widgets/graphicsview/boxes/qtbox.cpp
@@ -414,7 +414,7 @@ void QtBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWi
CircleItem::CircleItem(int size, int x, int y) : ItemBase(size, x, y)
{
- m_color = QColor::fromHsv(rand() % 360, 255, 255);
+ m_color = QColor::fromHsv(QRandomGenerator::global()->bounded(360), 255, 255);
}
void CircleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
diff --git a/examples/widgets/graphicsview/boxes/scene.cpp b/examples/widgets/graphicsview/boxes/scene.cpp
index 9ac429c667..f51cad99ac 100644
--- a/examples/widgets/graphicsview/boxes/scene.cpp
+++ b/examples/widgets/graphicsview/boxes/scene.cpp
@@ -50,9 +50,10 @@
#include <QDebug>
#include "scene.h"
+#include <QtCore/QRandomGenerator>
#include <QtGui/qmatrix4x4.h>
#include <QtGui/qvector3d.h>
-#include <cmath>
+#include <qmath.h>
#include "3rdparty/fbm.h"
@@ -868,11 +869,12 @@ void Scene::renderCubemaps()
QVector3D center;
+ const float eachAngle = 2 * M_PI / m_cubemaps.size();
for (int i = m_frame % N; i < m_cubemaps.size(); i += N) {
if (0 == m_cubemaps[i])
continue;
- float angle = 2.0f * PI * i / m_cubemaps.size();
+ float angle = i * eachAngle;
center = m_trackBalls[1].rotation().rotatedVector(QVector3D(std::cos(angle), std::sin(angle), 0.0f));
@@ -1071,13 +1073,16 @@ void Scene::newItem(ItemDialog::ItemType type)
QSize size = sceneRect().size().toSize();
switch (type) {
case ItemDialog::QtBoxItem:
- addItem(new QtBox(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32));
+ addItem(new QtBox(64, QRandomGenerator::global()->bounded(size.width() - 64) + 32,
+ QRandomGenerator::global()->bounded(size.height() - 64) + 32));
break;
case ItemDialog::CircleItem:
- addItem(new CircleItem(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32));
+ addItem(new CircleItem(64, QRandomGenerator::global()->bounded(size.width() - 64) + 32,
+ QRandomGenerator::global()->bounded(size.height() - 64) + 32));
break;
case ItemDialog::SquareItem:
- addItem(new SquareItem(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32));
+ addItem(new SquareItem(64, QRandomGenerator::global()->bounded(size.width() - 64) + 32,
+ QRandomGenerator::global()->bounded(size.height() - 64) + 32));
break;
default:
break;
diff --git a/examples/widgets/graphicsview/boxes/scene.h b/examples/widgets/graphicsview/boxes/scene.h
index a2ba1d0b5a..ccb6f368cd 100644
--- a/examples/widgets/graphicsview/boxes/scene.h
+++ b/examples/widgets/graphicsview/boxes/scene.h
@@ -63,8 +63,6 @@
#include "glbuffers.h"
#include "qtbox.h"
-#define PI 3.14159265358979
-
QT_BEGIN_NAMESPACE
class QMatrix4x4;
QT_END_NAMESPACE
diff --git a/examples/widgets/graphicsview/boxes/trackball.cpp b/examples/widgets/graphicsview/boxes/trackball.cpp
index 15f3af77d1..794ce7ac37 100644
--- a/examples/widgets/graphicsview/boxes/trackball.cpp
+++ b/examples/widgets/graphicsview/boxes/trackball.cpp
@@ -50,6 +50,7 @@
#include "trackball.h"
#include "scene.h"
+#include <qmath.h>
#include <cmath>
//============================================================================//
@@ -101,10 +102,11 @@ void TrackBall::move(const QPointF& p, const QQuaternion &transformation)
case Plane:
{
QLineF delta(m_lastPos, p);
- m_angularVelocity = 180*delta.length() / (PI*msecs);
+ const float angleDelta = qRadiansToDegrees(float(delta.length()));
+ m_angularVelocity = angleDelta / msecs;
m_axis = QVector3D(-delta.dy(), delta.dx(), 0.0f).normalized();
m_axis = transformation.rotatedVector(m_axis);
- m_rotation = QQuaternion::fromAxisAndAngle(m_axis, 180 / PI * delta.length()) * m_rotation;
+ m_rotation = QQuaternion::fromAxisAndAngle(m_axis, angleDelta) * m_rotation;
}
break;
case Sphere:
@@ -124,7 +126,7 @@ void TrackBall::move(const QPointF& p, const QQuaternion &transformation)
currentPos3D.normalize();
m_axis = QVector3D::crossProduct(lastPos3D, currentPos3D);
- float angle = 180 / PI * std::asin(std::sqrt(QVector3D::dotProduct(m_axis, m_axis)));
+ float angle = qRadiansToDegrees(std::asin(m_axis.length()));
m_angularVelocity = angle / msecs;
m_axis.normalize();
diff --git a/examples/widgets/graphicsview/collidingmice/main.cpp b/examples/widgets/graphicsview/collidingmice/main.cpp
index a0659b9bc1..91aee70b86 100644
--- a/examples/widgets/graphicsview/collidingmice/main.cpp
+++ b/examples/widgets/graphicsview/collidingmice/main.cpp
@@ -60,7 +60,6 @@ static const int MouseCount = 7;
int main(int argc, char **argv)
{
QApplication app(argc, argv);
- qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
//! [0]
//! [1]
diff --git a/examples/widgets/graphicsview/collidingmice/mouse.cpp b/examples/widgets/graphicsview/collidingmice/mouse.cpp
index b94c650c18..14f887f6e3 100644
--- a/examples/widgets/graphicsview/collidingmice/mouse.cpp
+++ b/examples/widgets/graphicsview/collidingmice/mouse.cpp
@@ -52,12 +52,12 @@
#include <QGraphicsScene>
#include <QPainter>
+#include <QRandomGenerator>
#include <QStyleOption>
+#include <qmath.h>
-#include <math.h>
-
-static const double Pi = 3.14159265358979323846264338327950288419717;
-static double TwoPi = 2.0 * Pi;
+const qreal Pi = M_PI;
+const qreal TwoPi = 2 * M_PI;
static qreal normalizeAngle(qreal angle)
{
@@ -71,9 +71,9 @@ static qreal normalizeAngle(qreal angle)
//! [0]
Mouse::Mouse()
: angle(0), speed(0), mouseEyeDirection(0),
- color(qrand() % 256, qrand() % 256, qrand() % 256)
+ color(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256))
{
- setRotation(qrand() % (360 * 16));
+ setRotation(QRandomGenerator::global()->bounded(360 * 16));
}
//! [0]
@@ -140,9 +140,7 @@ void Mouse::advance(int step)
//! [5]
QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
if (lineToCenter.length() > 150) {
- qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
- if (lineToCenter.dy() < 0)
- angleToCenter = TwoPi - angleToCenter;
+ qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx());
angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
if (angleToCenter < Pi && angleToCenter > Pi / 4) {
@@ -171,9 +169,7 @@ void Mouse::advance(int step)
continue;
QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
- qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
- if (lineToMouse.dy() < 0)
- angleToMouse = TwoPi - angleToMouse;
+ qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx());
angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
@@ -190,16 +186,16 @@ void Mouse::advance(int step)
// Add some random movement
//! [10]
- if (dangerMice.size() > 1 && (qrand() % 10) == 0) {
- if (qrand() % 1)
- angle += (qrand() % 100) / 500.0;
+ if (dangerMice.size() > 1 && QRandomGenerator::global()->bounded(10) == 0) {
+ if (QRandomGenerator::global()->bounded(1))
+ angle += QRandomGenerator::global()->bounded(1 / 500.0);
else
- angle -= (qrand() % 100) / 500.0;
+ angle -= QRandomGenerator::global()->bounded(1 / 500.0);
}
//! [10]
//! [11]
- speed += (-50 + qrand() % 100) / 100.0;
+ speed += (-50 + QRandomGenerator::global()->bounded(100)) / 100.0;
qreal dx = ::sin(angle) * 10;
mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5;
diff --git a/examples/widgets/graphicsview/diagramscene/arrow.cpp b/examples/widgets/graphicsview/diagramscene/arrow.cpp
index 012b9ea2ed..88160d9399 100644
--- a/examples/widgets/graphicsview/diagramscene/arrow.cpp
+++ b/examples/widgets/graphicsview/diagramscene/arrow.cpp
@@ -51,13 +51,10 @@
#include "arrow.h"
-#include <math.h>
-
+#include <qmath.h>
#include <QPen>
#include <QPainter>
-const qreal Pi = 3.14;
-
//! [0]
Arrow::Arrow(DiagramItem *startItem, DiagramItem *endItem, QGraphicsItem *parent)
: QGraphicsLineItem(parent)
@@ -132,14 +129,12 @@ void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
setLine(QLineF(intersectPoint, myStartItem->pos()));
//! [5] //! [6]
- double angle = ::acos(line().dx() / line().length());
- if (line().dy() >= 0)
- angle = (Pi * 2) - angle;
+ double angle = std::atan2(-line().dy(), line().dx());
- QPointF arrowP1 = line().p1() + QPointF(sin(angle + Pi / 3) * arrowSize,
- cos(angle + Pi / 3) * arrowSize);
- QPointF arrowP2 = line().p1() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
- cos(angle + Pi - Pi / 3) * arrowSize);
+ QPointF arrowP1 = line().p1() + QPointF(sin(angle + M_PI / 3) * arrowSize,
+ cos(angle + M_PI / 3) * arrowSize);
+ QPointF arrowP2 = line().p1() + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
+ cos(angle + M_PI - M_PI / 3) * arrowSize);
arrowHead.clear();
arrowHead << line().p1() << arrowP1 << arrowP2;
diff --git a/examples/widgets/graphicsview/diagramscene/diagramscene.pro b/examples/widgets/graphicsview/diagramscene/diagramscene.pro
index 7045f41d03..c19dcff3a9 100644
--- a/examples/widgets/graphicsview/diagramscene/diagramscene.pro
+++ b/examples/widgets/graphicsview/diagramscene/diagramscene.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(fontcombobox))
HEADERS = mainwindow.h \
diagramitem.h \
diff --git a/examples/widgets/graphicsview/dragdroprobot/coloritem.cpp b/examples/widgets/graphicsview/dragdroprobot/coloritem.cpp
index 64a715d31f..262e18a317 100644
--- a/examples/widgets/graphicsview/dragdroprobot/coloritem.cpp
+++ b/examples/widgets/graphicsview/dragdroprobot/coloritem.cpp
@@ -54,7 +54,7 @@
//! [0]
ColorItem::ColorItem()
- : color(qrand() % 256, qrand() % 256, qrand() % 256)
+ : color(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256))
{
setToolTip(QString("QColor(%1, %2, %3)\n%4")
.arg(color.red()).arg(color.green()).arg(color.blue())
@@ -107,7 +107,7 @@ void ColorItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
//! [6]
static int n = 0;
- if (n++ > 2 && (qrand() % 3) == 0) {
+ if (n++ > 2 && QRandomGenerator::global()->bounded(3) == 0) {
QImage image(":/images/head.png");
mime->setImageData(image);
diff --git a/examples/widgets/graphicsview/dragdroprobot/main.cpp b/examples/widgets/graphicsview/dragdroprobot/main.cpp
index 20cec92d26..045e184569 100644
--- a/examples/widgets/graphicsview/dragdroprobot/main.cpp
+++ b/examples/widgets/graphicsview/dragdroprobot/main.cpp
@@ -73,7 +73,6 @@ int main(int argc, char **argv)
{
QApplication app(argc, argv);
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
//! [0]
//! [1]
QGraphicsScene scene(-200, -200, 400, 400);
diff --git a/examples/widgets/graphicsview/elasticnodes/edge.cpp b/examples/widgets/graphicsview/elasticnodes/edge.cpp
index e794e803cf..aec12b4225 100644
--- a/examples/widgets/graphicsview/elasticnodes/edge.cpp
+++ b/examples/widgets/graphicsview/elasticnodes/edge.cpp
@@ -51,13 +51,9 @@
#include "edge.h"
#include "node.h"
-#include <math.h>
-
+#include <qmath.h>
#include <QPainter>
-static const double Pi = 3.14159265358979323846264338327950288419717;
-static double TwoPi = 2.0 * Pi;
-
//! [0]
Edge::Edge(Node *sourceNode, Node *destNode)
: arrowSize(10)
@@ -139,18 +135,16 @@ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
//! [6]
// Draw the arrows
- double angle = ::acos(line.dx() / line.length());
- if (line.dy() >= 0)
- angle = TwoPi - angle;
-
- QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * arrowSize,
- cos(angle + Pi / 3) * arrowSize);
- QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
- cos(angle + Pi - Pi / 3) * arrowSize);
- QPointF destArrowP1 = destPoint + QPointF(sin(angle - Pi / 3) * arrowSize,
- cos(angle - Pi / 3) * arrowSize);
- QPointF destArrowP2 = destPoint + QPointF(sin(angle - Pi + Pi / 3) * arrowSize,
- cos(angle - Pi + Pi / 3) * arrowSize);
+ double angle = std::atan2(-line.dy(), line.dx());
+
+ QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + M_PI / 3) * arrowSize,
+ cos(angle + M_PI / 3) * arrowSize);
+ QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
+ cos(angle + M_PI - M_PI / 3) * arrowSize);
+ QPointF destArrowP1 = destPoint + QPointF(sin(angle - M_PI / 3) * arrowSize,
+ cos(angle - M_PI / 3) * arrowSize);
+ QPointF destArrowP2 = destPoint + QPointF(sin(angle - M_PI + M_PI / 3) * arrowSize,
+ cos(angle - M_PI + M_PI / 3) * arrowSize);
painter->setBrush(Qt::black);
painter->drawPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2);
diff --git a/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp b/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp
index 844c8f8aac..4259aab803 100644
--- a/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp
+++ b/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp
@@ -55,6 +55,7 @@
#include <math.h>
#include <QKeyEvent>
+#include <QRandomGenerator>
//! [0]
GraphWidget::GraphWidget(QWidget *parent)
@@ -247,7 +248,7 @@ void GraphWidget::shuffle()
{
foreach (QGraphicsItem *item, scene()->items()) {
if (qgraphicsitem_cast<Node *>(item))
- item->setPos(-150 + qrand() % 300, -150 + qrand() % 300);
+ item->setPos(-150 + QRandomGenerator::global()->bounded(300), -150 + QRandomGenerator::global()->bounded(300));
}
}
diff --git a/examples/widgets/graphicsview/elasticnodes/main.cpp b/examples/widgets/graphicsview/elasticnodes/main.cpp
index 75cc4b0f69..1e372a9f6d 100644
--- a/examples/widgets/graphicsview/elasticnodes/main.cpp
+++ b/examples/widgets/graphicsview/elasticnodes/main.cpp
@@ -57,7 +57,6 @@
int main(int argc, char **argv)
{
QApplication app(argc, argv);
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
GraphWidget *widget = new GraphWidget;
diff --git a/examples/widgets/graphicsview/embeddeddialogs/embeddeddialogs.pro b/examples/widgets/graphicsview/embeddeddialogs/embeddeddialogs.pro
index 993a5f22b7..60c507fc3d 100644
--- a/examples/widgets/graphicsview/embeddeddialogs/embeddeddialogs.pro
+++ b/examples/widgets/graphicsview/embeddeddialogs/embeddeddialogs.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(fontcombobox))
SOURCES += main.cpp
SOURCES += customproxy.cpp embeddeddialog.cpp
diff --git a/examples/widgets/graphicsview/padnavigator/padnavigator.pro b/examples/widgets/graphicsview/padnavigator/padnavigator.pro
index c2bc79b5cc..53a57c85d7 100644
--- a/examples/widgets/graphicsview/padnavigator/padnavigator.pro
+++ b/examples/widgets/graphicsview/padnavigator/padnavigator.pro
@@ -17,6 +17,7 @@ FORMS += \
form.ui
QT += widgets
+requires(qtConfig(treewidget))
qtHaveModule(opengl): QT += opengl
# install
diff --git a/examples/widgets/itemviews/addressbook/addressbook.pro b/examples/widgets/itemviews/addressbook/addressbook.pro
index 5e2f1bcbbc..498b2574ce 100644
--- a/examples/widgets/itemviews/addressbook/addressbook.pro
+++ b/examples/widgets/itemviews/addressbook/addressbook.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(listview))
SOURCES = adddialog.cpp \
addresswidget.cpp \
diff --git a/examples/widgets/itemviews/addressbook/addresswidget.cpp b/examples/widgets/itemviews/addressbook/addresswidget.cpp
index cff35ad78f..143f6266dd 100644
--- a/examples/widgets/itemviews/addressbook/addresswidget.cpp
+++ b/examples/widgets/itemviews/addressbook/addresswidget.cpp
@@ -85,10 +85,7 @@ void AddressWidget::showAddEntryDialog()
//! [3]
void AddressWidget::addEntry(QString name, QString address)
{
- QList<QPair<QString, QString> >list = table->getList();
- QPair<QString, QString> pair(name, address);
-
- if (!list.contains(pair)) {
+ if (!table->getContacts().contains({ name, address })) {
table->insertRows(0, 1, QModelIndex());
QModelIndex index = table->index(0, 0, QModelIndex());
@@ -195,6 +192,12 @@ void AddressWidget::setupTabs()
&QItemSelectionModel::selectionChanged,
this, &AddressWidget::selectionChanged);
+ connect(this, &QTabWidget::currentChanged, this, [this](int tabIndex) {
+ auto *tableView = qobject_cast<QTableView *>(widget(tabIndex));
+ if (tableView)
+ emit selectionChanged(tableView->selectionModel()->selection());
+ });
+
addTab(tableView, str);
}
}
@@ -211,18 +214,16 @@ void AddressWidget::readFromFile(const QString &fileName)
return;
}
- QList<QPair<QString, QString> > pairs = table->getList();
+ QList<Contact> contacts;
QDataStream in(&file);
- in >> pairs;
+ in >> contacts;
- if (pairs.isEmpty()) {
+ if (contacts.isEmpty()) {
QMessageBox::information(this, tr("No contacts in file"),
tr("The file you are attempting to open contains no contacts."));
} else {
- for (int i=0; i<pairs.size(); ++i) {
- QPair<QString, QString> p = pairs.at(i);
- addEntry(p.first, p.second);
- }
+ for (const auto &contact: qAsConst(contacts))
+ addEntry(contact.name, contact.address);
}
}
//! [7]
@@ -237,8 +238,7 @@ void AddressWidget::writeToFile(const QString &fileName)
return;
}
- QList<QPair<QString, QString> > pairs = table->getList();
QDataStream out(&file);
- out << pairs;
+ out << table->getContacts();
}
//! [6]
diff --git a/examples/widgets/itemviews/addressbook/tablemodel.cpp b/examples/widgets/itemviews/addressbook/tablemodel.cpp
index d701ef3223..674e312753 100644
--- a/examples/widgets/itemviews/addressbook/tablemodel.cpp
+++ b/examples/widgets/itemviews/addressbook/tablemodel.cpp
@@ -56,10 +56,10 @@ TableModel::TableModel(QObject *parent)
{
}
-TableModel::TableModel(QList<QPair<QString, QString> > pairs, QObject *parent)
+TableModel::TableModel(QList<Contact> contacts, QObject *parent)
: QAbstractTableModel(parent)
+ , contacts(contacts)
{
- listOfPairs = pairs;
}
//! [0]
@@ -67,7 +67,7 @@ TableModel::TableModel(QList<QPair<QString, QString> > pairs, QObject *parent)
int TableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
- return listOfPairs.size();
+ return contacts.size();
}
int TableModel::columnCount(const QModelIndex &parent) const
@@ -83,16 +83,16 @@ QVariant TableModel::data(const QModelIndex &index, int role) const
if (!index.isValid())
return QVariant();
- if (index.row() >= listOfPairs.size() || index.row() < 0)
+ if (index.row() >= contacts.size() || index.row() < 0)
return QVariant();
if (role == Qt::DisplayRole) {
- QPair<QString, QString> pair = listOfPairs.at(index.row());
+ const auto &contact = contacts.at(index.row());
if (index.column() == 0)
- return pair.first;
+ return contact.name;
else if (index.column() == 1)
- return pair.second;
+ return contact.address;
}
return QVariant();
}
@@ -126,10 +126,8 @@ bool TableModel::insertRows(int position, int rows, const QModelIndex &index)
Q_UNUSED(index);
beginInsertRows(QModelIndex(), position, position + rows - 1);
- for (int row = 0; row < rows; ++row) {
- QPair<QString, QString> pair(" ", " ");
- listOfPairs.insert(position, pair);
- }
+ for (int row = 0; row < rows; ++row)
+ contacts.insert(position, { QString(), QString() });
endInsertRows();
return true;
@@ -142,9 +140,8 @@ bool TableModel::removeRows(int position, int rows, const QModelIndex &index)
Q_UNUSED(index);
beginRemoveRows(QModelIndex(), position, position + rows - 1);
- for (int row = 0; row < rows; ++row) {
- listOfPairs.removeAt(position);
- }
+ for (int row = 0; row < rows; ++row)
+ contacts.removeAt(position);
endRemoveRows();
return true;
@@ -157,16 +154,16 @@ bool TableModel::setData(const QModelIndex &index, const QVariant &value, int ro
if (index.isValid() && role == Qt::EditRole) {
int row = index.row();
- QPair<QString, QString> p = listOfPairs.value(row);
+ auto contact = contacts.value(row);
if (index.column() == 0)
- p.first = value.toString();
+ contact.name = value.toString();
else if (index.column() == 1)
- p.second = value.toString();
+ contact.address = value.toString();
else
return false;
- listOfPairs.replace(row, p);
+ contacts.replace(row, contact);
emit(dataChanged(index, index));
return true;
@@ -187,8 +184,8 @@ Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
//! [7]
//! [8]
-QList< QPair<QString, QString> > TableModel::getList()
+QList<Contact> TableModel::getContacts() const
{
- return listOfPairs;
+ return contacts;
}
//! [8]
diff --git a/examples/widgets/itemviews/addressbook/tablemodel.h b/examples/widgets/itemviews/addressbook/tablemodel.h
index 9a669c508d..1004a35d31 100644
--- a/examples/widgets/itemviews/addressbook/tablemodel.h
+++ b/examples/widgets/itemviews/addressbook/tablemodel.h
@@ -53,16 +53,37 @@
#include <QAbstractTableModel>
#include <QList>
-#include <QPair>
//! [0]
+
+struct Contact
+{
+ QString name;
+ QString address;
+
+ bool operator==(const Contact &other) const
+ {
+ return name == other.name && address == other.address;
+ }
+};
+
+inline QDataStream &operator<<(QDataStream &stream, const Contact &contact)
+{
+ return stream << contact.name << contact.address;
+}
+
+inline QDataStream &operator>>(QDataStream &stream, Contact &contact)
+{
+ return stream >> contact.name >> contact.address;
+}
+
class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
TableModel(QObject *parent = 0);
- TableModel(QList<QPair<QString, QString> > listofPairs, QObject *parent = 0);
+ TableModel(QList<Contact> contacts, QObject *parent = 0);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
@@ -72,10 +93,10 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
- QList<QPair<QString, QString> > getList();
+ QList<Contact> getContacts() const;
private:
- QList<QPair<QString, QString> > listOfPairs;
+ QList<Contact> contacts;
};
//! [0]
diff --git a/examples/widgets/itemviews/basicsortfiltermodel/basicsortfiltermodel.pro b/examples/widgets/itemviews/basicsortfiltermodel/basicsortfiltermodel.pro
index 2469a4ef20..c8087666fe 100644
--- a/examples/widgets/itemviews/basicsortfiltermodel/basicsortfiltermodel.pro
+++ b/examples/widgets/itemviews/basicsortfiltermodel/basicsortfiltermodel.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = window.h
SOURCES = main.cpp \
diff --git a/examples/widgets/itemviews/chart/chart.pro b/examples/widgets/itemviews/chart/chart.pro
index 4b64b01e8a..323f6202e4 100644
--- a/examples/widgets/itemviews/chart/chart.pro
+++ b/examples/widgets/itemviews/chart/chart.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = mainwindow.h \
pieview.h
diff --git a/examples/widgets/itemviews/chart/pieview.cpp b/examples/widgets/itemviews/chart/pieview.cpp
index fb439fae67..3f85e397ee 100644
--- a/examples/widgets/itemviews/chart/pieview.cpp
+++ b/examples/widgets/itemviews/chart/pieview.cpp
@@ -49,12 +49,8 @@
****************************************************************************/
#include <QtWidgets>
+#include <qmath.h>
#include <cmath>
-
-#ifndef M_PI
-#define M_PI 3.1415927
-#endif
-
#include "pieview.h"
PieView::PieView(QWidget *parent)
@@ -125,9 +121,9 @@ QModelIndex PieView::indexAt(const QPoint &point) const
return QModelIndex();
// Determine the angle of the point.
- double angle = (180 / M_PI) * std::acos(cx / d);
- if (cy < 0)
- angle = 360 - angle;
+ double angle = qRadiansToDegrees(std::atan2(cy, cx));
+ if (angle < 0)
+ angle = 360 + angle;
// Find the relevant slice of the pie.
double startAngle = 0.0;
diff --git a/examples/widgets/itemviews/coloreditorfactory/coloreditorfactory.pro b/examples/widgets/itemviews/coloreditorfactory/coloreditorfactory.pro
index 82cb264ddd..2d16ab5e2b 100644
--- a/examples/widgets/itemviews/coloreditorfactory/coloreditorfactory.pro
+++ b/examples/widgets/itemviews/coloreditorfactory/coloreditorfactory.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = colorlisteditor.h \
window.h
diff --git a/examples/widgets/itemviews/combowidgetmapper/combowidgetmapper.pro b/examples/widgets/itemviews/combowidgetmapper/combowidgetmapper.pro
index 37f82fa5ae..a5bbc2abe0 100644
--- a/examples/widgets/itemviews/combowidgetmapper/combowidgetmapper.pro
+++ b/examples/widgets/itemviews/combowidgetmapper/combowidgetmapper.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = window.h
SOURCES = main.cpp \
diff --git a/examples/widgets/itemviews/customsortfiltermodel/customsortfiltermodel.pro b/examples/widgets/itemviews/customsortfiltermodel/customsortfiltermodel.pro
index 630beddcb8..60fd94103d 100644
--- a/examples/widgets/itemviews/customsortfiltermodel/customsortfiltermodel.pro
+++ b/examples/widgets/itemviews/customsortfiltermodel/customsortfiltermodel.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(treeview))
HEADERS = mysortfilterproxymodel.h \
window.h \
diff --git a/examples/widgets/itemviews/dirview/dirview.pro b/examples/widgets/itemviews/dirview/dirview.pro
index 511ec0ed98..981a64a7d6 100644
--- a/examples/widgets/itemviews/dirview/dirview.pro
+++ b/examples/widgets/itemviews/dirview/dirview.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(treeview))
SOURCES = main.cpp
diff --git a/examples/widgets/itemviews/editabletreemodel/editabletreemodel.pro b/examples/widgets/itemviews/editabletreemodel/editabletreemodel.pro
index a6c1e5563f..a157a90761 100644
--- a/examples/widgets/itemviews/editabletreemodel/editabletreemodel.pro
+++ b/examples/widgets/itemviews/editabletreemodel/editabletreemodel.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(treeview))
FORMS = mainwindow.ui
HEADERS = mainwindow.h \
diff --git a/examples/widgets/itemviews/fetchmore/fetchmore.pro b/examples/widgets/itemviews/fetchmore/fetchmore.pro
index eb4275da19..164033f0a2 100644
--- a/examples/widgets/itemviews/fetchmore/fetchmore.pro
+++ b/examples/widgets/itemviews/fetchmore/fetchmore.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(listview))
HEADERS = filelistmodel.h \
window.h
diff --git a/examples/widgets/itemviews/frozencolumn/frozencolumn.pro b/examples/widgets/itemviews/frozencolumn/frozencolumn.pro
index 717ba40a9d..cf7a9eecac 100644
--- a/examples/widgets/itemviews/frozencolumn/frozencolumn.pro
+++ b/examples/widgets/itemviews/frozencolumn/frozencolumn.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(tableview))
HEADERS += freezetablewidget.h
SOURCES += main.cpp freezetablewidget.cpp
diff --git a/examples/widgets/itemviews/interview/interview.pro b/examples/widgets/itemviews/interview/interview.pro
index 0e480e939c..6d64f23eb9 100644
--- a/examples/widgets/itemviews/interview/interview.pro
+++ b/examples/widgets/itemviews/interview/interview.pro
@@ -1,5 +1,6 @@
TEMPLATE = app
QT += widgets
+requires(qtConfig(treeview))
HEADERS += model.h
SOURCES += model.cpp main.cpp
diff --git a/examples/widgets/itemviews/pixelator/pixelator.pro b/examples/widgets/itemviews/pixelator/pixelator.pro
index 35176a6026..421f626e28 100644
--- a/examples/widgets/itemviews/pixelator/pixelator.pro
+++ b/examples/widgets/itemviews/pixelator/pixelator.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(tableview))
qtHaveModule(printsupport): QT += printsupport
HEADERS = imagemodel.h \
diff --git a/examples/widgets/itemviews/puzzle/main.cpp b/examples/widgets/itemviews/puzzle/main.cpp
index 1f5e7ee9b2..d013bf078d 100644
--- a/examples/widgets/itemviews/puzzle/main.cpp
+++ b/examples/widgets/itemviews/puzzle/main.cpp
@@ -58,7 +58,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
MainWindow window;
- window.loadImage(":/images/example.jpg");
+ window.loadImage(QStringLiteral(":/images/example.jpg"));
window.show();
return app.exec();
}
diff --git a/examples/widgets/itemviews/puzzle/mainwindow.cpp b/examples/widgets/itemviews/puzzle/mainwindow.cpp
index 282a7b477b..d598dc9017 100644
--- a/examples/widgets/itemviews/puzzle/mainwindow.cpp
+++ b/examples/widgets/itemviews/puzzle/mainwindow.cpp
@@ -69,12 +69,19 @@ MainWindow::MainWindow(QWidget *parent)
void MainWindow::openImage()
{
- const QString fileName =
- QFileDialog::getOpenFileName(this,
- tr("Open Image"), QString(),
- tr("Image Files (*.png *.jpg *.bmp)"));
- if (!fileName.isEmpty())
- loadImage(fileName);
+ const QString directory =
+ QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::homePath());
+ QFileDialog dialog(this, tr("Open Image"), directory);
+ dialog.setAcceptMode(QFileDialog::AcceptOpen);
+ dialog.setFileMode(QFileDialog::ExistingFile);
+ QStringList mimeTypeFilters;
+ for (const QByteArray &mimeTypeName : QImageReader::supportedMimeTypes())
+ mimeTypeFilters.append(mimeTypeName);
+ mimeTypeFilters.sort();
+ dialog.setMimeTypeFilters(mimeTypeFilters);
+ dialog.selectMimeTypeFilter("image/jpeg");
+ if (dialog.exec() == QDialog::Accepted)
+ loadImage(dialog.selectedFiles().constFirst());
}
void MainWindow::loadImage(const QString &fileName)
@@ -83,7 +90,7 @@ void MainWindow::loadImage(const QString &fileName)
if (!newImage.load(fileName)) {
QMessageBox::warning(this, tr("Open Image"),
tr("The image file could not be loaded."),
- QMessageBox::Cancel);
+ QMessageBox::Close);
return;
}
puzzleImage = newImage;
@@ -107,8 +114,6 @@ void MainWindow::setupPuzzle()
(puzzleImage.height() - size) / 2, size, size).scaled(puzzleWidget->imageSize(),
puzzleWidget->imageSize(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- qsrand(QCursor::pos().x() ^ QCursor::pos().y());
-
model->addPieces(puzzleImage);
puzzleWidget->clear();
}
@@ -117,19 +122,15 @@ void MainWindow::setupMenus()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
- QAction *openAction = fileMenu->addAction(tr("&Open..."));
+ QAction *openAction = fileMenu->addAction(tr("&Open..."), this, &MainWindow::openImage);
openAction->setShortcuts(QKeySequence::Open);
- QAction *exitAction = fileMenu->addAction(tr("E&xit"));
+ QAction *exitAction = fileMenu->addAction(tr("E&xit"), qApp, &QCoreApplication::quit);
exitAction->setShortcuts(QKeySequence::Quit);
QMenu *gameMenu = menuBar()->addMenu(tr("&Game"));
- QAction *restartAction = gameMenu->addAction(tr("&Restart"));
-
- connect(openAction, &QAction::triggered, this, &MainWindow::openImage);
- connect(exitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
- connect(restartAction, &QAction::triggered, this, &MainWindow::setupPuzzle);
+ gameMenu->addAction(tr("&Restart"), this, &MainWindow::setupPuzzle);
}
void MainWindow::setupWidgets()
diff --git a/examples/widgets/itemviews/puzzle/mainwindow.h b/examples/widgets/itemviews/puzzle/mainwindow.h
index 7e27dc6f3a..208d3a5281 100644
--- a/examples/widgets/itemviews/puzzle/mainwindow.h
+++ b/examples/widgets/itemviews/puzzle/mainwindow.h
@@ -65,7 +65,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- MainWindow(QWidget *parent = 0);
+ explicit MainWindow(QWidget *parent = nullptr);
public slots:
void openImage();
diff --git a/examples/widgets/itemviews/puzzle/piecesmodel.cpp b/examples/widgets/itemviews/puzzle/piecesmodel.cpp
index 0fbf0cdcc2..f0649d3776 100644
--- a/examples/widgets/itemviews/puzzle/piecesmodel.cpp
+++ b/examples/widgets/itemviews/puzzle/piecesmodel.cpp
@@ -52,6 +52,7 @@
#include <QIcon>
#include <QMimeData>
+#include <QRandomGenerator>
PiecesModel::PiecesModel(int pieceSize, QObject *parent)
: QAbstractListModel(parent), m_PieceSize(pieceSize)
@@ -77,7 +78,7 @@ QVariant PiecesModel::data(const QModelIndex &index, int role) const
void PiecesModel::addPiece(const QPixmap &pixmap, const QPoint &location)
{
int row;
- if (int(2.0 * qrand() / (RAND_MAX + 1.0)) == 1)
+ if (QRandomGenerator::global()->bounded(2) == 1)
row = 0;
else
row = pixmaps.size();
diff --git a/examples/widgets/itemviews/puzzle/puzzle.pro b/examples/widgets/itemviews/puzzle/puzzle.pro
index 55f1d7e709..dcc27aae6a 100644
--- a/examples/widgets/itemviews/puzzle/puzzle.pro
+++ b/examples/widgets/itemviews/puzzle/puzzle.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(listview))
HEADERS = mainwindow.h \
piecesmodel.h \
diff --git a/examples/widgets/itemviews/puzzle/puzzlewidget.cpp b/examples/widgets/itemviews/puzzle/puzzlewidget.cpp
index 78931a95a3..06968da80f 100644
--- a/examples/widgets/itemviews/puzzle/puzzlewidget.cpp
+++ b/examples/widgets/itemviews/puzzle/puzzlewidget.cpp
@@ -62,9 +62,7 @@ PuzzleWidget::PuzzleWidget(int imageSize, QWidget *parent)
void PuzzleWidget::clear()
{
- pieceLocations.clear();
- piecePixmaps.clear();
- pieceRects.clear();
+ pieces.clear();
highlightedRect = QRect();
inPlace = 0;
update();
@@ -110,23 +108,20 @@ void PuzzleWidget::dropEvent(QDropEvent *event)
&& findPiece(targetSquare(event->pos())) == -1) {
QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece");
- QDataStream stream(&pieceData, QIODevice::ReadOnly);
- QRect square = targetSquare(event->pos());
- QPixmap pixmap;
- QPoint location;
- stream >> pixmap >> location;
+ QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
+ Piece piece;
+ piece.rect = targetSquare(event->pos());
+ dataStream >> piece.pixmap >> piece.location;
- pieceLocations.append(location);
- piecePixmaps.append(pixmap);
- pieceRects.append(square);
+ pieces.append(piece);
highlightedRect = QRect();
- update(square);
+ update(piece.rect);
event->setDropAction(Qt::MoveAction);
event->accept();
- if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize())) {
+ if (piece.location == piece.rect.topLeft() / pieceSize()) {
inPlace++;
if (inPlace == 25)
emit puzzleCompleted();
@@ -139,8 +134,8 @@ void PuzzleWidget::dropEvent(QDropEvent *event)
int PuzzleWidget::findPiece(const QRect &pieceRect) const
{
- for (int i = 0; i < pieceRects.size(); ++i) {
- if (pieceRect == pieceRects[i])
+ for (int i = 0, size = pieces.size(); i < size; ++i) {
+ if (pieces.at(i).rect == pieceRect)
return i;
}
return -1;
@@ -154,13 +149,9 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
if (found == -1)
return;
- QPoint location = pieceLocations[found];
- QPixmap pixmap = piecePixmaps[found];
- pieceLocations.removeAt(found);
- piecePixmaps.removeAt(found);
- pieceRects.removeAt(found);
+ Piece piece = pieces.takeAt(found);
- if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize()))
+ if (piece.location == square.topLeft() / pieceSize())
inPlace--;
update(square);
@@ -168,7 +159,7 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
- dataStream << pixmap << location;
+ dataStream << piece.pixmap << piece.location;
QMimeData *mimeData = new QMimeData;
mimeData->setData("image/x-puzzle-piece", itemData);
@@ -176,23 +167,20 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(event->pos() - square.topLeft());
- drag->setPixmap(pixmap);
+ drag->setPixmap(piece.pixmap);
- if (drag->start(Qt::MoveAction) == 0) {
- pieceLocations.insert(found, location);
- piecePixmaps.insert(found, pixmap);
- pieceRects.insert(found, square);
+ if (drag->start(Qt::MoveAction) == Qt::IgnoreAction) {
+ pieces.insert(found, piece);
update(targetSquare(event->pos()));
- if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize()))
+ if (piece.location == QPoint(square.x() / pieceSize(), square.y() / pieceSize()))
inPlace++;
}
}
void PuzzleWidget::paintEvent(QPaintEvent *event)
{
- QPainter painter;
- painter.begin(this);
+ QPainter painter(this);
painter.fillRect(event->rect(), Qt::white);
if (highlightedRect.isValid()) {
@@ -201,15 +189,14 @@ void PuzzleWidget::paintEvent(QPaintEvent *event)
painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1));
}
- for (int i = 0; i < pieceRects.size(); ++i) {
- painter.drawPixmap(pieceRects[i], piecePixmaps[i]);
- }
- painter.end();
+ for (const Piece &piece : pieces)
+ painter.drawPixmap(piece.rect, piece.pixmap);
}
const QRect PuzzleWidget::targetSquare(const QPoint &position) const
{
- return QRect(position.x()/pieceSize() * pieceSize(), position.y()/pieceSize() * pieceSize(), pieceSize(), pieceSize());
+ return QRect(position / pieceSize() * pieceSize(),
+ QSize(pieceSize(), pieceSize()));
}
int PuzzleWidget::pieceSize() const
diff --git a/examples/widgets/itemviews/puzzle/puzzlewidget.h b/examples/widgets/itemviews/puzzle/puzzlewidget.h
index 137e0b7162..40dd654af6 100644
--- a/examples/widgets/itemviews/puzzle/puzzlewidget.h
+++ b/examples/widgets/itemviews/puzzle/puzzlewidget.h
@@ -51,9 +51,9 @@
#ifndef PUZZLEWIDGET_H
#define PUZZLEWIDGET_H
-#include <QList>
-#include <QPixmap>
#include <QPoint>
+#include <QPixmap>
+#include <QVector>
#include <QWidget>
QT_BEGIN_NAMESPACE
@@ -67,7 +67,7 @@ class PuzzleWidget : public QWidget
Q_OBJECT
public:
- explicit PuzzleWidget(int imageSize, QWidget *parent = 0);
+ explicit PuzzleWidget(int imageSize, QWidget *parent = nullptr);
void clear();
int pieceSize() const;
@@ -85,12 +85,16 @@ protected:
void paintEvent(QPaintEvent *event) override;
private:
+ struct Piece {
+ QPixmap pixmap;
+ QRect rect;
+ QPoint location;
+ };
+
int findPiece(const QRect &pieceRect) const;
const QRect targetSquare(const QPoint &position) const;
- QList<QPixmap> piecePixmaps;
- QList<QRect> pieceRects;
- QList<QPoint> pieceLocations;
+ QVector<Piece> pieces;
QRect highlightedRect;
int inPlace;
int m_ImageSize;
diff --git a/examples/widgets/itemviews/simpledommodel/simpledommodel.pro b/examples/widgets/itemviews/simpledommodel/simpledommodel.pro
index db15632ba9..3d45920e36 100644
--- a/examples/widgets/itemviews/simpledommodel/simpledommodel.pro
+++ b/examples/widgets/itemviews/simpledommodel/simpledommodel.pro
@@ -6,6 +6,7 @@ SOURCES = domitem.cpp \
main.cpp \
mainwindow.cpp
QT += xml widgets
+requires(qtConfig(filedialog))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/simpledommodel
diff --git a/examples/widgets/itemviews/simpletreemodel/simpletreemodel.pro b/examples/widgets/itemviews/simpletreemodel/simpletreemodel.pro
index 82484c9971..41afb54382 100644
--- a/examples/widgets/itemviews/simpletreemodel/simpletreemodel.pro
+++ b/examples/widgets/itemviews/simpletreemodel/simpletreemodel.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(treeview))
HEADERS = treeitem.h \
treemodel.h
diff --git a/examples/widgets/itemviews/simplewidgetmapper/simplewidgetmapper.pro b/examples/widgets/itemviews/simplewidgetmapper/simplewidgetmapper.pro
index 1d5cca3f01..f86a16bd3f 100644
--- a/examples/widgets/itemviews/simplewidgetmapper/simplewidgetmapper.pro
+++ b/examples/widgets/itemviews/simplewidgetmapper/simplewidgetmapper.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(datawidgetmapper))
HEADERS = window.h
SOURCES = main.cpp \
diff --git a/examples/widgets/itemviews/spinboxdelegate/spinboxdelegate.pro b/examples/widgets/itemviews/spinboxdelegate/spinboxdelegate.pro
index d0430d8470..2a6fed223a 100644
--- a/examples/widgets/itemviews/spinboxdelegate/spinboxdelegate.pro
+++ b/examples/widgets/itemviews/spinboxdelegate/spinboxdelegate.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(tableview))
HEADERS = delegate.h
SOURCES = delegate.cpp \
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheet.pro b/examples/widgets/itemviews/spreadsheet/spreadsheet.pro
index 56f7424a93..afdf9d9d7a 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheet.pro
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheet.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(treeview))
qtHaveModule(printsupport): QT += printsupport
#unix:qtHaveModule(dbus): QT += dbus widgets
diff --git a/examples/widgets/itemviews/stardelegate/stardelegate.pro b/examples/widgets/itemviews/stardelegate/stardelegate.pro
index 95d1367fbb..7e8f252e16 100644
--- a/examples/widgets/itemviews/stardelegate/stardelegate.pro
+++ b/examples/widgets/itemviews/stardelegate/stardelegate.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(tablewidget))
HEADERS = stardelegate.h \
stareditor.h \
diff --git a/examples/widgets/itemviews/storageview/main.cpp b/examples/widgets/itemviews/storageview/main.cpp
index c8057186fc..f349e58fad 100644
--- a/examples/widgets/itemviews/storageview/main.cpp
+++ b/examples/widgets/itemviews/storageview/main.cpp
@@ -51,6 +51,7 @@
#include <QtWidgets/QApplication>
#include <QtWidgets/QHeaderView>
+#include <QtWidgets/QShortcut>
#include <QtWidgets/QTreeView>
#include "storagemodel.h"
@@ -60,9 +61,16 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
QTreeView view;
- view.setModel(new StorageModel(&view));
view.resize(640, 480);
+ view.setWindowTitle("Storage View");
view.setSelectionBehavior(QAbstractItemView::SelectRows);
+
+ StorageModel *model = new StorageModel(&view);
+ model->refresh();
+ QShortcut *refreshShortcut = new QShortcut(Qt::CTRL + Qt::Key_R, &view);
+ QObject::connect(refreshShortcut, &QShortcut::activated, model, &StorageModel::refresh);
+ view.setModel(model);
+
int columnCount = view.model()->columnCount();
for (int c = 0; c < columnCount; ++c)
view.resizeColumnToContents(c);
diff --git a/examples/widgets/itemviews/storageview/storagemodel.cpp b/examples/widgets/itemviews/storageview/storagemodel.cpp
index b7c594f8f7..063f126d86 100644
--- a/examples/widgets/itemviews/storageview/storagemodel.cpp
+++ b/examples/widgets/itemviews/storageview/storagemodel.cpp
@@ -52,29 +52,27 @@
#include "storagemodel.h"
#include <QDir>
+#include <QLocale>
#include <qmath.h>
+#include <algorithm>
#include <cmath>
-static QString sizeToString(qint64 size)
+StorageModel::StorageModel(QObject *parent) :
+ QAbstractTableModel(parent)
{
- static const char *const strings[] = { "b", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
-
- if (size <= 0)
- return StorageModel::tr("0 b");
-
- double power = std::log((double)size)/std::log(1024.0);
- int intPower = (int)power;
- intPower = intPower >= 8 ? 8 - 1 : intPower;
-
- double normSize = size / std::pow(1024.0, intPower);
- //: this should expand to "1.23 GB"
- return StorageModel::tr("%1 %2").arg(normSize, 0, 'f', intPower > 0 ? 2 : 0).arg(strings[intPower]);
}
-StorageModel::StorageModel(QObject *parent) :
- QAbstractTableModel(parent),
- m_volumes(QStorageInfo::mountedVolumes())
+void StorageModel::refresh()
{
+ beginResetModel();
+ m_volumes = QStorageInfo::mountedVolumes();
+ std::sort(m_volumes.begin(), m_volumes.end(),
+ [](const QStorageInfo &st1, const QStorageInfo &st2) {
+ static const QString rootSortString = QStringLiteral(" ");
+ return (st1.isRoot() ? rootSortString : st1.rootPath())
+ < (st2.isRoot() ? rootSortString : st2.rootPath());
+ });
+ endResetModel();
}
int StorageModel::columnCount(const QModelIndex &/*parent*/) const
@@ -89,6 +87,22 @@ int StorageModel::rowCount(const QModelIndex &parent) const
return m_volumes.count();
}
+Qt::ItemFlags StorageModel::flags(const QModelIndex &index) const
+{
+ Qt::ItemFlags result = QAbstractTableModel::flags(index);
+ switch (index.column()) {
+ case ColumnAvailable:
+ case ColumnIsReady:
+ case ColumnIsReadOnly:
+ case ColumnIsValid:
+ result |= Qt::ItemIsUserCheckable;
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
QVariant StorageModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
@@ -106,11 +120,17 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
case ColumnFileSystemName:
return volume.fileSystemType();
case ColumnTotal:
- return sizeToString(volume.bytesTotal());
+ return QLocale().formattedDataSize(volume.bytesTotal());
case ColumnFree:
- return sizeToString(volume.bytesFree());
+ return QLocale().formattedDataSize(volume.bytesFree());
case ColumnAvailable:
- return sizeToString(volume.bytesAvailable());
+ return QLocale().formattedDataSize(volume.bytesAvailable());
+ default:
+ break;
+ }
+ } else if (role == Qt::CheckStateRole) {
+ const QStorageInfo &volume = m_volumes.at(index.row());
+ switch (index.column()) {
case ColumnIsReady:
return volume.isReady();
case ColumnIsReadOnly:
@@ -120,7 +140,18 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
default:
break;
}
+ } else if (role == Qt::TextAlignmentRole) {
+ switch (index.column()) {
+ case ColumnTotal:
+ case ColumnFree:
+ case ColumnAvailable:
+ return Qt::AlignTrailing;
+ default:
+ break;
+ }
+ return Qt::AlignLeading;
} else if (role == Qt::ToolTipRole) {
+ QLocale locale;
const QStorageInfo &volume = m_volumes.at(index.row());
return tr("Root path : %1\n"
"Name: %2\n"
@@ -140,9 +171,9 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
arg(volume.displayName()).
arg(QString::fromUtf8(volume.device())).
arg(QString::fromUtf8(volume.fileSystemType())).
- arg(sizeToString(volume.bytesTotal())).
- arg(sizeToString(volume.bytesFree())).
- arg(sizeToString(volume.bytesAvailable())).
+ arg(locale.formattedDataSize(volume.bytesTotal())).
+ arg(locale.formattedDataSize(volume.bytesFree())).
+ arg(locale.formattedDataSize(volume.bytesAvailable())).
arg(volume.isReady() ? tr("true") : tr("false")).
arg(volume.isReadOnly() ? tr("true") : tr("false")).
arg(volume.isValid() ? tr("true") : tr("false")).
@@ -161,13 +192,13 @@ QVariant StorageModel::headerData(int section, Qt::Orientation orientation, int
switch (section) {
case ColumnRootPath:
- return tr("Root path");
+ return tr("Root Path");
case ColumnName:
return tr("Volume Name");
case ColumnDevice:
return tr("Device");
case ColumnFileSystemName:
- return tr("File system");
+ return tr("File System");
case ColumnTotal:
return tr("Total");
case ColumnFree:
diff --git a/examples/widgets/itemviews/storageview/storagemodel.h b/examples/widgets/itemviews/storageview/storagemodel.h
index 2b37414d8d..787b2f04de 100644
--- a/examples/widgets/itemviews/storageview/storagemodel.h
+++ b/examples/widgets/itemviews/storageview/storagemodel.h
@@ -74,13 +74,17 @@ public:
ColumnCount
};
- explicit StorageModel(QObject *parent = 0);
+ explicit StorageModel(QObject *parent = nullptr);
- int columnCount(const QModelIndex &parent) const;
- int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const override;
+ int rowCount(const QModelIndex &parent) const override;
- QVariant data(const QModelIndex &index, int role) const;
- QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ QVariant data(const QModelIndex &index, int role) const override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+
+public slots:
+ void refresh();
private:
QList<QStorageInfo> m_volumes;
diff --git a/examples/widgets/itemviews/storageview/storageview.pro b/examples/widgets/itemviews/storageview/storageview.pro
index 07e7fb5145..2fdb78e7b8 100644
--- a/examples/widgets/itemviews/storageview/storageview.pro
+++ b/examples/widgets/itemviews/storageview/storageview.pro
@@ -1,4 +1,5 @@
QT += core gui widgets
+requires(qtConfig(treeview))
TARGET = storageview
TEMPLATE = app
SOURCES += storagemodel.cpp \
diff --git a/examples/widgets/layouts/basiclayouts/basiclayouts.pro b/examples/widgets/layouts/basiclayouts/basiclayouts.pro
index 0ff1347743..3df4a63b20 100644
--- a/examples/widgets/layouts/basiclayouts/basiclayouts.pro
+++ b/examples/widgets/layouts/basiclayouts/basiclayouts.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = dialog.h
SOURCES = dialog.cpp \
diff --git a/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pro b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pro
index c2ca53546c..dcd4288698 100644
--- a/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pro
+++ b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = dialog.h
SOURCES = dialog.cpp \
diff --git a/examples/widgets/mainwindows/application/application.pro b/examples/widgets/mainwindows/application/application.pro
index 0f451754f2..e55655a934 100644
--- a/examples/widgets/mainwindows/application/application.pro
+++ b/examples/widgets/mainwindows/application/application.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = mainwindow.h
SOURCES = main.cpp \
diff --git a/examples/widgets/mainwindows/dockwidgets/dockwidgets.pro b/examples/widgets/mainwindows/dockwidgets/dockwidgets.pro
index 9cd3128a66..3acded5ed3 100644
--- a/examples/widgets/mainwindows/dockwidgets/dockwidgets.pro
+++ b/examples/widgets/mainwindows/dockwidgets/dockwidgets.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(listwidget))
qtHaveModule(printsupport): QT += printsupport
HEADERS = mainwindow.h
diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
index 10e3dd045a..afceddfca1 100644
--- a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
+++ b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
@@ -63,7 +63,6 @@
#include <QFileDialog>
#include <QDialogButtonBox>
#include <QMessageBox>
-#include <QSignalMapper>
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.pro b/examples/widgets/mainwindows/mainwindow/mainwindow.pro
index bf92d0e3ca..446d07ee6e 100644
--- a/examples/widgets/mainwindows/mainwindow/mainwindow.pro
+++ b/examples/widgets/mainwindows/mainwindow/mainwindow.pro
@@ -1,5 +1,6 @@
TEMPLATE = app
QT += widgets
+requires(qtConfig(combobox))
HEADERS += colorswatch.h mainwindow.h toolbar.h
SOURCES += colorswatch.cpp mainwindow.cpp toolbar.cpp main.cpp
diff --git a/examples/widgets/mainwindows/mainwindow/toolbar.cpp b/examples/widgets/mainwindows/mainwindow/toolbar.cpp
index 97152a64a3..814cfc7f4d 100644
--- a/examples/widgets/mainwindows/mainwindow/toolbar.cpp
+++ b/examples/widgets/mainwindows/mainwindow/toolbar.cpp
@@ -50,6 +50,8 @@
#include "toolbar.h"
+#include <QRandomGenerator>
+
#include <QMainWindow>
#include <QMenu>
#include <QPainter>
@@ -257,7 +259,7 @@ void ToolBar::randomize()
QList<QAction *> randomized;
QList<QAction *> actions = this->actions();
while (!actions.isEmpty()) {
- QAction *action = actions.takeAt(rand() % actions.size());
+ QAction *action = actions.takeAt(QRandomGenerator::global()->bounded(actions.size()));
randomized.append(action);
}
clear();
diff --git a/examples/widgets/mainwindows/mdi/mdi.pro b/examples/widgets/mainwindows/mdi/mdi.pro
index 2e3c232a56..f2c236f7e2 100644
--- a/examples/widgets/mainwindows/mdi/mdi.pro
+++ b/examples/widgets/mainwindows/mdi/mdi.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = mainwindow.h \
mdichild.h
diff --git a/examples/widgets/mainwindows/sdi/sdi.pro b/examples/widgets/mainwindows/sdi/sdi.pro
index 83f1c0f805..30d07b0665 100644
--- a/examples/widgets/mainwindows/sdi/sdi.pro
+++ b/examples/widgets/mainwindows/sdi/sdi.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = mainwindow.h
SOURCES = main.cpp \
diff --git a/examples/widgets/painting/affine/xform.cpp b/examples/widgets/painting/affine/xform.cpp
index e47bc9d251..20f6eb3c6d 100644
--- a/examples/widgets/painting/affine/xform.cpp
+++ b/examples/widgets/painting/affine/xform.cpp
@@ -77,8 +77,8 @@ XFormView::XFormView(QWidget *parent)
pts->setBoundingRect(QRectF(0, 0, 500, 500));
ctrlPoints << QPointF(250, 250) << QPointF(350, 250);
pts->setPoints(ctrlPoints);
- connect(pts, SIGNAL(pointsChanged(QPolygonF)),
- this, SLOT(updateCtrlPoints(QPolygonF)));
+ connect(pts, &HoverPoints::pointsChanged,
+ this,&XFormView::updateCtrlPoints);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}
@@ -876,29 +876,29 @@ XFormWidget::XFormWidget(QWidget *parent)
#endif
mainGroupLayout->addWidget(whatsThisButton);
- connect(rotateSlider, SIGNAL(valueChanged(int)), view, SLOT(changeRotation(int)));
- connect(shearSlider, SIGNAL(valueChanged(int)), view, SLOT(changeShear(int)));
- connect(scaleSlider, SIGNAL(valueChanged(int)), view, SLOT(changeScale(int)));
-
- connect(vectorType, SIGNAL(clicked()), view, SLOT(setVectorType()));
- connect(pixmapType, SIGNAL(clicked()), view, SLOT(setPixmapType()));
- connect(textType, SIGNAL(clicked()), view, SLOT(setTextType()));
- connect(textType, SIGNAL(toggled(bool)), textEditor, SLOT(setEnabled(bool)));
- connect(textEditor, SIGNAL(textChanged(QString)), view, SLOT(setText(QString)));
-
- connect(view, SIGNAL(rotationChanged(int)), rotateSlider, SLOT(setValue(int)));
- connect(view, SIGNAL(scaleChanged(int)), scaleSlider, SLOT(setValue(int)));
- connect(view, SIGNAL(shearChanged(int)), shearSlider, SLOT(setValue(int)));
-
- connect(resetButton, SIGNAL(clicked()), view, SLOT(reset()));
- connect(animateButton, SIGNAL(clicked(bool)), view, SLOT(setAnimation(bool)));
- connect(whatsThisButton, SIGNAL(clicked(bool)), view, SLOT(setDescriptionEnabled(bool)));
- connect(whatsThisButton, SIGNAL(clicked(bool)), view->hoverPoints(), SLOT(setDisabled(bool)));
- connect(view, SIGNAL(descriptionEnabledChanged(bool)), view->hoverPoints(), SLOT(setDisabled(bool)));
- connect(view, SIGNAL(descriptionEnabledChanged(bool)), whatsThisButton, SLOT(setChecked(bool)));
- connect(showSourceButton, SIGNAL(clicked()), view, SLOT(showSource()));
+ connect(rotateSlider, &QSlider::valueChanged, view, &XFormView::changeRotation);
+ connect(shearSlider, &QSlider::valueChanged, view, &XFormView::changeShear);
+ connect(scaleSlider, &QSlider::valueChanged, view, &XFormView::changeScale);
+
+ connect(vectorType, &QRadioButton::clicked, view, &XFormView::setVectorType);
+ connect(pixmapType, &QRadioButton::clicked, view, &XFormView::setPixmapType);
+ connect(textType, &QRadioButton::clicked, view, &XFormView::setTextType);
+ connect(textType, &QRadioButton::toggled, textEditor, &XFormView::setEnabled);
+ connect(textEditor, &QLineEdit::textChanged, view, &XFormView::setText);
+
+ connect(view, &XFormView::rotationChanged, rotateSlider, &QSlider::setValue);
+ connect(view, &XFormView::scaleChanged, scaleSlider, &QAbstractSlider::setValue);
+ connect(view, &XFormView::shearChanged, shearSlider, &QAbstractSlider::setValue);
+
+ connect(resetButton, &QPushButton::clicked, view, &XFormView::reset);
+ connect(animateButton, &QPushButton::clicked, view, &XFormView::setAnimation);
+ connect(whatsThisButton, &QPushButton::clicked, view, &ArthurFrame::setDescriptionEnabled);
+ connect(whatsThisButton, &QPushButton::clicked, view->hoverPoints(), &HoverPoints::setDisabled);
+ connect(view, &XFormView::descriptionEnabledChanged, view->hoverPoints(), &HoverPoints::setDisabled);
+ connect(view, &XFormView::descriptionEnabledChanged, whatsThisButton, &QPushButton::setChecked);
+ connect(showSourceButton, &QPushButton::clicked, view, &XFormView::showSource);
#ifdef QT_OPENGL_SUPPORT
- connect(enableOpenGLButton, SIGNAL(clicked(bool)), view, SLOT(enableOpenGL(bool)));
+ connect(enableOpenGLButton, &QPushButton::clicked, view, &XFormView::enableOpenGL);
#endif
view->loadSourceFile(":res/affine/xform.cpp");
view->loadDescription(":res/affine/xform.html");
diff --git a/examples/widgets/painting/basicdrawing/basicdrawing.pro b/examples/widgets/painting/basicdrawing/basicdrawing.pro
index a7b3cff9cd..aba62a3683 100644
--- a/examples/widgets/painting/basicdrawing/basicdrawing.pro
+++ b/examples/widgets/painting/basicdrawing/basicdrawing.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = renderarea.h \
window.h
diff --git a/examples/widgets/painting/composition/composition.cpp b/examples/widgets/painting/composition/composition.cpp
index d5d674fd83..0b57d3c7d3 100644
--- a/examples/widgets/painting/composition/composition.cpp
+++ b/examples/widgets/painting/composition/composition.cpp
@@ -464,7 +464,7 @@ void CompositionRenderer::paint(QPainter *painter)
drawBase(p);
}
- memcpy(m_buffer.bits(), m_base_buffer.bits(), m_buffer.byteCount());
+ memcpy(m_buffer.bits(), m_base_buffer.bits(), m_buffer.sizeInBytes());
{
QPainter p(&m_buffer);
diff --git a/examples/widgets/painting/fontsampler/fontsampler.pro b/examples/widgets/painting/fontsampler/fontsampler.pro
index 08dd07bc08..5d3461f4b8 100644
--- a/examples/widgets/painting/fontsampler/fontsampler.pro
+++ b/examples/widgets/painting/fontsampler/fontsampler.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
qtHaveModule(printsupport): QT += printsupport
FORMS = mainwindowbase.ui
diff --git a/examples/widgets/painting/imagecomposition/imagecomposition.pro b/examples/widgets/painting/imagecomposition/imagecomposition.pro
index 42c70471c1..3b7275c4f1 100644
--- a/examples/widgets/painting/imagecomposition/imagecomposition.pro
+++ b/examples/widgets/painting/imagecomposition/imagecomposition.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = imagecomposer.h
SOURCES = imagecomposer.cpp \
diff --git a/examples/widgets/painting/painterpaths/painterpaths.pro b/examples/widgets/painting/painterpaths/painterpaths.pro
index dfff238dd1..ab238434e6 100644
--- a/examples/widgets/painting/painterpaths/painterpaths.pro
+++ b/examples/widgets/painting/painterpaths/painterpaths.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = renderarea.h \
window.h
diff --git a/examples/widgets/painting/painterpaths/window.cpp b/examples/widgets/painting/painterpaths/window.cpp
index 7122411a6c..a987937b39 100644
--- a/examples/widgets/painting/painterpaths/window.cpp
+++ b/examples/widgets/painting/painterpaths/window.cpp
@@ -53,11 +53,7 @@
#include <QtWidgets>
-#include <cmath>
-
-//! [0]
-const float Pi = 3.14159f;
-//! [0]
+#include <qmath.h>
//! [1]
Window::Window()
@@ -133,8 +129,8 @@ Window::Window()
QPainterPath starPath;
starPath.moveTo(90, 50);
for (int i = 1; i < 5; ++i) {
- starPath.lineTo(50 + 40 * std::cos(0.8 * i * Pi),
- 50 + 40 * std::sin(0.8 * i * Pi));
+ starPath.lineTo(50 + 40 * std::cos(0.8 * i * M_PI),
+ 50 + 40 * std::sin(0.8 * i * M_PI));
}
starPath.closeSubpath();
//! [9]
diff --git a/examples/widgets/painting/transformations/transformations.pro b/examples/widgets/painting/transformations/transformations.pro
index 3f5398a228..e97dc87145 100644
--- a/examples/widgets/painting/transformations/transformations.pro
+++ b/examples/widgets/painting/transformations/transformations.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = renderarea.h \
window.h
diff --git a/examples/widgets/richtext/calendar/calendar.pro b/examples/widgets/richtext/calendar/calendar.pro
index 5adb99aac3..199c1dbb8d 100644
--- a/examples/widgets/richtext/calendar/calendar.pro
+++ b/examples/widgets/richtext/calendar/calendar.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = mainwindow.h
SOURCES = main.cpp \
diff --git a/examples/widgets/richtext/orderform/orderform.pro b/examples/widgets/richtext/orderform/orderform.pro
index 0eb9da3ae1..a24ac495cd 100644
--- a/examples/widgets/richtext/orderform/orderform.pro
+++ b/examples/widgets/richtext/orderform/orderform.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(tablewidget))
qtHaveModule(printsupport): QT += printsupport
HEADERS = detailsdialog.h \
diff --git a/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro
index ae51662341..e0d26bdbe0 100644
--- a/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro
+++ b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = highlighter.h \
mainwindow.h
diff --git a/examples/widgets/richtext/textedit/textedit.pro b/examples/widgets/richtext/textedit/textedit.pro
index c32bf68f68..b7a2155b0b 100644
--- a/examples/widgets/richtext/textedit/textedit.pro
+++ b/examples/widgets/richtext/textedit/textedit.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
qtHaveModule(printsupport): QT += printsupport
TEMPLATE = app
diff --git a/examples/widgets/statemachine/rogue/window.cpp b/examples/widgets/statemachine/rogue/window.cpp
index 428d4c3af6..3515138382 100644
--- a/examples/widgets/statemachine/rogue/window.cpp
+++ b/examples/widgets/statemachine/rogue/window.cpp
@@ -248,11 +248,9 @@ void Window::movePlayer(Direction direction)
void Window::setupMap()
{
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
-
for (int x = 0; x < WIDTH; ++x)
for (int y = 0; y < HEIGHT; ++y) {
- if (x == 0 || x == WIDTH - 1 || y == 0 || y == HEIGHT - 1 || qrand() % 40 == 0)
+ if (x == 0 || x == WIDTH - 1 || y == 0 || y == HEIGHT - 1 || QRandomGenerator::global()->bounded(40) == 0)
map[x][y] = '#';
else
map[x][y] = '.';
diff --git a/examples/widgets/tools/codecs/codecs.pro b/examples/widgets/tools/codecs/codecs.pro
index 2bdb130268..13daa79237 100644
--- a/examples/widgets/tools/codecs/codecs.pro
+++ b/examples/widgets/tools/codecs/codecs.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS += mainwindow.h \
previewform.h
diff --git a/examples/widgets/tools/completer/completer.pro b/examples/widgets/tools/completer/completer.pro
index cbc6ec85b5..c616e08468 100644
--- a/examples/widgets/tools/completer/completer.pro
+++ b/examples/widgets/tools/completer/completer.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(completer))
HEADERS = fsmodel.h \
mainwindow.h
diff --git a/examples/widgets/tools/customcompleter/customcompleter.pro b/examples/widgets/tools/customcompleter/customcompleter.pro
index 499fab5537..74c2ceb320 100644
--- a/examples/widgets/tools/customcompleter/customcompleter.pro
+++ b/examples/widgets/tools/customcompleter/customcompleter.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(completer))
HEADERS = mainwindow.h \
textedit.h
diff --git a/examples/widgets/tools/i18n/i18n.pro b/examples/widgets/tools/i18n/i18n.pro
index 8bfdd07a63..a4d5e418ea 100644
--- a/examples/widgets/tools/i18n/i18n.pro
+++ b/examples/widgets/tools/i18n/i18n.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(listwidget))
HEADERS = languagechooser.h \
mainwindow.h
diff --git a/examples/widgets/tools/plugandpaint/plugandpaint.pro b/examples/widgets/tools/plugandpaint/plugandpaint.pro
index f7da8a52bd..58c4dbbb6e 100644
--- a/examples/widgets/tools/plugandpaint/plugandpaint.pro
+++ b/examples/widgets/tools/plugandpaint/plugandpaint.pro
@@ -1,3 +1,6 @@
+QT_FOR_CONFIG += widgets
+requires(qtConfig(inputdialog))
+
TEMPLATE = subdirs
SUBDIRS = plugins app
diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp
index c929ff6922..92620ddd8c 100644
--- a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp
+++ b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp
@@ -50,13 +50,11 @@
#include <QtWidgets>
-#include <cmath>
+#include <qmath.h>
#include <stdlib.h>
#include "basictoolsplugin.h"
-const float Pi = 3.14159f;
-
//! [0]
QStringList BasicToolsPlugin::brushes() const
{
@@ -103,7 +101,7 @@ QRect BasicToolsPlugin::mouseMove(const QString &brush, QPainter &painter,
thickness, thickness);
}
} else if (brush == tr("Random Letters")) {
- QChar ch('A' + (qrand() % 26));
+ QChar ch(QRandomGenerator::global()->bounded('A', 'Z' + 1));
QFont biggerFont = painter.font();
biggerFont.setBold(true);
@@ -149,8 +147,8 @@ QPainterPath BasicToolsPlugin::generateShape(const QString &shape,
} else if (shape == tr("Star")) {
path.moveTo(90, 50);
for (int i = 1; i < 5; ++i) {
- path.lineTo(50 + 40 * std::cos(0.8 * i * Pi),
- 50 + 40 * std::sin(0.8 * i * Pi));
+ path.lineTo(50 + 40 * std::cos(0.8 * i * M_PI),
+ 50 + 40 * std::sin(0.8 * i * M_PI));
}
path.closeSubpath();
} else if (shape == tr("Text...")) {
diff --git a/examples/widgets/tools/regexp/regexp.pro b/examples/widgets/tools/regexp/regexp.pro
index f80c16fb60..a4c2971c25 100644
--- a/examples/widgets/tools/regexp/regexp.pro
+++ b/examples/widgets/tools/regexp/regexp.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = regexpdialog.h
SOURCES = regexpdialog.cpp \
diff --git a/examples/widgets/tools/regularexpression/regularexpression.pro b/examples/widgets/tools/regularexpression/regularexpression.pro
index 8e72e171b8..cc23402b9d 100644
--- a/examples/widgets/tools/regularexpression/regularexpression.pro
+++ b/examples/widgets/tools/regularexpression/regularexpression.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(treewidget))
HEADERS = regularexpressiondialog.h
SOURCES = regularexpressiondialog.cpp \
diff --git a/examples/widgets/tools/settingseditor/settingseditor.pro b/examples/widgets/tools/settingseditor/settingseditor.pro
index 5e605f1941..4880b7e582 100644
--- a/examples/widgets/tools/settingseditor/settingseditor.pro
+++ b/examples/widgets/tools/settingseditor/settingseditor.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(tablewidget))
HEADERS = locationdialog.h \
mainwindow.h \
diff --git a/examples/widgets/tools/treemodelcompleter/treemodelcompleter.pro b/examples/widgets/tools/treemodelcompleter/treemodelcompleter.pro
index 9f2b1ca9e4..ec25e0fc1c 100644
--- a/examples/widgets/tools/treemodelcompleter/treemodelcompleter.pro
+++ b/examples/widgets/tools/treemodelcompleter/treemodelcompleter.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(completer))
HEADERS = treemodelcompleter.h \
mainwindow.h
diff --git a/examples/widgets/tools/undo/mainwindow.cpp b/examples/widgets/tools/undo/mainwindow.cpp
index aa570caa80..5976163f3f 100644
--- a/examples/widgets/tools/undo/mainwindow.cpp
+++ b/examples/widgets/tools/undo/mainwindow.cpp
@@ -52,6 +52,7 @@
#include <QUndoStack>
#include <QFileDialog>
#include <QMessageBox>
+#include <QRandomGenerator>
#include <QTextStream>
#include <QToolButton>
#include "document.h"
@@ -321,7 +322,7 @@ void MainWindow::newDocument()
static QColor randomColor()
{
- int r = (int) (3.0*(rand()/(RAND_MAX + 1.0)));
+ int r = QRandomGenerator::global()->bounded(3);
switch (r) {
case 0:
return Qt::red;
@@ -337,10 +338,10 @@ static QRect randomRect(const QSize &s)
{
QSize min = Shape::minSize;
- int left = (int) ((0.0 + s.width() - min.width())*(rand()/(RAND_MAX + 1.0)));
- int top = (int) ((0.0 + s.height() - min.height())*(rand()/(RAND_MAX + 1.0)));
- int width = (int) ((0.0 + s.width() - left - min.width())*(rand()/(RAND_MAX + 1.0))) + min.width();
- int height = (int) ((0.0 + s.height() - top - min.height())*(rand()/(RAND_MAX + 1.0))) + min.height();
+ int left = (int) ((0.0 + s.width() - min.width())*(QRandomGenerator::global()->bounded(1.0)));
+ int top = (int) ((0.0 + s.height() - min.height())*(QRandomGenerator::global()->bounded(1.0)));
+ int width = (int) ((0.0 + s.width() - left - min.width())*(QRandomGenerator::global()->bounded(1.0))) + min.width();
+ int height = (int) ((0.0 + s.height() - top - min.height())*(QRandomGenerator::global()->bounded(1.0))) + min.height();
return QRect(left, top, width, height);
}
diff --git a/examples/widgets/tools/undo/undo.pro b/examples/widgets/tools/undo/undo.pro
index 3727c8cbde..9b7b577dd3 100644
--- a/examples/widgets/tools/undo/undo.pro
+++ b/examples/widgets/tools/undo/undo.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(undoview))
SOURCES += main.cpp mainwindow.cpp commands.cpp document.cpp
HEADERS += mainwindow.h commands.h document.h
diff --git a/examples/widgets/tools/undoframework/diagramitem.cpp b/examples/widgets/tools/undoframework/diagramitem.cpp
index 754baa2377..723645c9b2 100644
--- a/examples/widgets/tools/undoframework/diagramitem.cpp
+++ b/examples/widgets/tools/undoframework/diagramitem.cpp
@@ -65,8 +65,7 @@ DiagramItem::DiagramItem(DiagramType diagramType, QGraphicsItem *item)
setPolygon(trianglePolygon);
}
- QColor color(static_cast<int>(qrand()) % 256,
- static_cast<int>(qrand()) % 256, static_cast<int>(qrand()) % 256);
+ QColor color(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256));
QBrush brush(color);
setBrush(brush);
setFlag(QGraphicsItem::ItemIsSelectable);
diff --git a/examples/widgets/tools/undoframework/undoframework.pro b/examples/widgets/tools/undoframework/undoframework.pro
index 5c877be338..9f7fbc3375 100644
--- a/examples/widgets/tools/undoframework/undoframework.pro
+++ b/examples/widgets/tools/undoframework/undoframework.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(undoview))
HEADERS = commands.h \
diagramitem.h \
diff --git a/examples/widgets/tutorials/addressbook/part6/part6.pro b/examples/widgets/tutorials/addressbook/part6/part6.pro
index 02473e2bfe..6796f30a73 100644
--- a/examples/widgets/tutorials/addressbook/part6/part6.pro
+++ b/examples/widgets/tutorials/addressbook/part6/part6.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
SOURCES = addressbook.cpp \
finddialog.cpp \
diff --git a/examples/widgets/tutorials/addressbook/part7/part7.pro b/examples/widgets/tutorials/addressbook/part7/part7.pro
index bab6a593d6..6a99799c67 100644
--- a/examples/widgets/tutorials/addressbook/part7/part7.pro
+++ b/examples/widgets/tutorials/addressbook/part7/part7.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
SOURCES = addressbook.cpp \
finddialog.cpp \
diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part5/part5.pro b/examples/widgets/tutorials/gettingStarted/gsQt/part5/part5.pro
index 032f220b83..12378f305a 100644
--- a/examples/widgets/tutorials/gettingStarted/gsQt/part5/part5.pro
+++ b/examples/widgets/tutorials/gettingStarted/gsQt/part5/part5.pro
@@ -1,5 +1,5 @@
-
QT += widgets
+requires(qtConfig(filedialog))
SOURCES = main.cpp
# install
diff --git a/examples/widgets/tutorials/gettingstartedqt.qdoc b/examples/widgets/tutorials/gettingstartedqt.qdoc
new file mode 100644
index 0000000000..921dd7a32d
--- /dev/null
+++ b/examples/widgets/tutorials/gettingstartedqt.qdoc
@@ -0,0 +1,559 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example tutorials/notepad
+ \title Getting Started Programming with Qt Widgets
+ \brief A tutorial for Qt Widgets based on a notepad application
+
+ In this topic, we teach basic Qt knowledge by implementing a simple
+ Notepad application using C++ and the \l{Qt Widgets} module. The
+ application is a small text editor which allows you to create a text
+ file, save it, print it,
+ or reopen and edit it again. You can also set the font to be used.
+
+ \image notepad1.png "Notepad application"
+
+ You can find the final Notepad source files in the qtdoc repository
+ in the tutorials/notepad directory. You can either fetch
+ the Qt 5 sources from Qt Project or install them as part of Qt 5.
+ The application is also available in the example list of Qt Creator's
+ Welcome mode.
+
+ \section1 Creating the Notepad Project
+
+ Setting up a new project in Qt Creator is aided by a wizard that
+ guides you step-by-step through the project creation process. The
+ wizard prompts you to enter the settings needed for that particular
+ type of project and creates the project for you.
+
+ \image notepad2.png "Qt Creator New File or Project dialog"
+
+ To create the Notepad project, select \b File > \b{New File or
+ Project} > \b Applications > \b {Qt Widgets Application} > \b Choose,
+ and follow the instructions of the wizard. In the
+ \b{Class Information}
+ dialog, type \b Notepad as the class name and select \b QMainWindow
+ as the base class.
+
+ \image notepad3.png "Class Information Dialog"
+
+ The \b {Qt Widgets Application} wizard creates a project that contains
+ a main source file and a set of files that specify a user interface
+ (Notepad widget):
+
+ \list
+ \li notepad.pro - the project file.
+ \li main.cpp - the main source file for the application.
+ \li notepad.cpp - the source file of the notepad class of the
+ Notepad widget.
+ \li notepad.h - the header file of the notepad class for the
+ Notepad widget.
+ \li notepad.ui - the UI form for the Notepad widget.
+ \endlist
+
+ The .cpp, .h, and .ui files come with the necessary boiler plate code
+ for you to be able to build and run the project. The .pro file is
+ complete.
+ We will take a closer look at the file contents in the following
+ sections.
+
+ \b{Learn More}
+
+ \table
+ \header
+ \li About
+ \li Here
+ \row
+ \li Using Qt Creator
+ \li \l{Qt Creator Manual}{Qt Creator}
+ \row
+ \li Creating other kind of applications with Qt Creator
+ \li \l{Qt Creator: Tutorials}{Qt Creator Tutorials}
+ \endtable
+
+
+ \section1 Main Source File
+
+ The wizard generates the following code in the main.cpp file:
+
+ \quotefromfile tutorials/notepad/main.cpp
+ \skipto "notepad.h"
+ \printuntil EditorApp.exec()
+ \printuntil }
+
+ We will go through the code line by line. The following lines include
+ the header files for the Notepad widget and QApplication. All Qt classes
+ have a header file named after them.
+
+ \quotefromfile tutorials/notepad/main.cpp
+ \skipto notepad.h
+ \printuntil QApplication
+
+ The following line defines the main function that is the entry point
+ for all C and C++ based applications:
+
+ \printline main
+
+ The following line creates a QApplication object. This object manages
+ application-wide resources and is necessary to run any Qt program
+ that uses Qt Widgets. It constructs an application object with \c argc
+ command line arguments run in \c argv. (For GUI applications that
+ do not use Qt Widgets, you can use QGuiApplication instead.)
+
+ \skipuntil {
+ \printuntil QApplication
+
+ The following line creates the Notepad object. This is the object for
+ which the wizard created the class and the UI file. The user interface
+ contains visual elements that are called \c widgets in Qt. Examples
+ of widgets are text edits, scroll bars, labels, and radio buttons. A
+ widget can also be a container for other widgets; a dialog or a main
+ application window, for example.
+
+ \printline Notepad
+
+ The following line shows the Notepad widget on the screen in its own
+ window. Widgets can also function as containers. An example of this
+ is QMainWindow which often contains several types of widgets. Widgets
+ are not visible by default; the function \l{QWidget::}{show()} makes
+ the widget visible.
+
+ \printline Editor.show
+
+ The following line makes the QApplication enter its event loop. When
+ a Qt application is running, events are generated and sent to the
+ widgets of the application. Examples of events are mouse presses
+ and key strokes.
+
+ \printline EditorApp.exec
+
+ \b{Learn More}
+
+ \table
+ \header
+ \li About
+ \li Here
+ \row
+ \li Widgets and Window Geometry
+ \li \l{Window and Dialog Widgets}
+ \row
+ \li Events and event handling
+ \li \l{The Event System}
+ \endtable
+
+ \section1 Designing a UI
+
+ The wizard generates a user interface definition in XML format: notepad.ui.
+ When you open the notepad.ui file in Qt Creator, it automatically
+ opens in the integrated Qt Designer.
+
+ When you build the application, Qt Creator launches the Qt
+ \l{User Interface Compiler (uic)} that reads the .ui file and creates
+ a corresponding C++ header file, ui_notepad.h.
+
+ \section2 Using Qt Designer
+
+ The wizard creates an application that uses a QMainWindow. It has
+ its own layout to which you can add a menu bar, dock widgets, toolbars,
+ and a status bar. The center area can be occupied by any kind of widget.
+ The wizard places the Notepad widget there.
+
+ To add widgets in Qt Designer:
+
+ \list 1
+ \li In the Qt Creator \b Editor mode, double-click the notepad.ui
+ file in the \b Projects view to launch the file in the integrated
+ Qt Designer.
+ \li Drag and drop widgets Text Edit (QTextEdit) to the form.
+ \li Press \b {Ctrl+A} (or \b {Cmd+A}) to select the widgets and click
+ \b {Lay out Vertically} (or press \b {Ctrl+L}) to apply a vertical
+ layout (QVBoxLayout).
+ \li Press \b {Ctrl+S} (or \b {Cmd+S}) to save your changes.
+ \endlist
+
+ The UI now looks as follows in Qt Designer:
+
+ \image notepad4.png
+
+ You can view the generated XML file in the code editor:
+
+ \quotefromfile tutorials/notepad/notepad.ui
+
+ \printuntil QMenuBar
+ \dots
+
+ The following line contains the XML declaration, which specifies the
+ XML version and character encoding used in the document:
+
+ \code
+ <?xml version="1.0" encoding="UTF-8"?>
+ \endcode
+
+ The rest of the file specifies an \c ui element that defines a
+ Notepad widget:
+
+ \code
+ <ui version="4.0">
+ \endcode
+
+ The UI file is used together with the header and source file of the
+ Notepad class. We will look at the rest of the UI file in the later
+ sections.
+
+ \section2 Notepad Header File
+
+ The wizard generated a header file for the Notepad class that has the
+ necessary #includes, a constructor, a destructor, and the Ui object.
+ The file looks as follows:
+
+ \snippet tutorials/notepad/notepad.h all
+
+ The following line includes QMainWindow that provides a main application
+ window:
+
+ \snippet tutorials/notepad/notepad.h 1
+
+ The following lines declare the Notepad class in the Ui namespace,
+ which is the standard namespace for the UI classes generated from
+ .ui files by the \c uic tool:
+
+ \snippet tutorials/notepad/notepad.h 2
+
+ The class declaration contains the \c Q_OBJECT macro. It must come
+ first in the class definition, and declares our class as a QObject.
+ Naturally, it must also inherit from QObject. A QObject adds several
+ abilities to a normal C++ class. Notably, the class name and slot
+ names can be queried at runtime. It is also possible to query a slot's
+ parameter types and invoke it.
+
+ \snippet tutorials/notepad/notepad.h 3
+
+ The following lines declare a constructor that has a default argument
+ called \c parent.
+ The value 0 indicates that the widget has no parent (it is a top-level
+ widget).
+
+ \snippet tutorials/notepad/notepad.h 4
+
+ The following line declares a virtual destructor to free the resources
+ that were acquired by the object during its life-cycle. According to
+ the C++ naming convention, destructors have the same name as the class
+ they are associated with, prefixed with a tilde (~). In QObject,
+ destructors are virtual to ensure that the destructors of derived
+ classes are invoked properly when an object is deleted through a
+ pointer-to-base-class.
+
+ \snippet tutorials/notepad/notepad.h 5
+
+ The following lines declare a member variable which is a pointer to
+ the Notepad UI class. A member variable is associated with a specific
+ class, and accessible for all its methods.
+
+ \snippet tutorials/notepad/notepad.h 6
+
+ \section2 Notepad Source File
+
+ The source file that the wizard generated for the Notepad class looks
+ as follows:
+
+ \quotefromfile tutorials/notepad/notepad.cpp
+ \skipto notepad.h
+ \printuntil ui->textEdit->setFont(font)
+ \printuntil }
+
+ The following lines include the Notepad class header file that was
+ generated by the wizard and the UI header file that was generated
+ by the \c uic tool:
+
+ \quotefromfile tutorials/notepad/notepad.cpp
+ \skipto notepad.h
+ \printuntil ui_notepad
+
+ The following line defines the \c {Notepad} constructor:
+
+ \skipto Notepad::Notepad
+ \printline Notepad::Notepad
+
+ The following line calls the QMainWindow constructor, which is
+ the base class for the Notepad class:
+
+ \printline QMainWindow
+
+ The following line creates the UI class instance and assigns it to
+ the \c ui member:
+
+ \printline ui(new
+
+ The following line sets up the UI:
+
+ \quotefromfile tutorials/notepad/notepad.cpp
+ \skipto ui->setupUi
+ \printline ui->setupUi(this)
+
+ In the destructor, we delete the \c ui:
+
+ \skipto Notepad::~Notepad
+ \printuntil }
+
+ In order to have the text edit field occupy the whole screen, we add
+ \c setCentralWidget to the main window.
+
+ \quotefromfile tutorials/notepad/notepad.cpp
+ \skipto Notepad::Notepad(QWidget *parent)
+ \printuntil }
+
+ \section2 Project File
+
+ The wizard generates the following project file, \c {notepad.pro}, for
+ us:
+
+ \quotefile tutorials/notepad/notepad.pro
+
+ The project file specifies the application name and the \c qmake
+ template to use for generating the project, as well as the source,
+ header, and UI files included in the project.
+
+ You could also use \c qmake's \c -project option to generate the \.pro
+ file. Although, in that case, you have to remember to add the line
+ \c{QT += widgets} to the generated file in order to link against the
+ Qt Widgets Module.
+
+ \b{Learn More}
+
+ \table
+ \header
+ \li About
+ \li Here
+ \row
+ \li Using Qt Designer
+ \li \l{Qt Designer Manual}
+ \row
+ \li Layouts
+ \li \l{Layout Management},
+ \l{Widgets and Layouts},
+ \l{Layout Examples}
+ \row
+ \li The widgets that come with Qt
+ \li \l{Qt Widget Gallery}
+ \row
+ \li Main windows and main window classes
+ \li \l{Application Main Window},
+ \l{Main Window Examples}
+ \row
+ \li QObjects and the Qt Object model (This is essential to
+ understand Qt)
+ \li \l{Object Model}
+ \row
+ \li qmake and the Qt build system
+ \li \l{qmake Manual}
+ \endtable
+
+ \section1 Adding User Interaction
+
+
+ To add functionality to the editor, we start by adding menu items
+ and buttons on a toolbar.
+
+ Click on "Type Here", and add the options New, Open, Save, Save as,
+ Print and Exit. This creates 5 lines in the Action Editor below.
+ To connect the actions to slots, right-click an action and select
+ Go to slot > triggered(), and complete the code for that given slot.
+
+ If we also want to add the actions to a toolbar, we can assign an
+ icon to each QAction, and then drag the QAction to the toolbar. You
+ assign an icon by entering an icon name in the Icon property of the
+ action concerned. When the QAction has been dragged to the toolbar,
+ clicking the icon will launch the associated slot.
+
+ Complete the method \c on_actionNew_triggered():
+
+ \quotefromfile tutorials/notepad/notepad.cpp
+ \skipto on_actionNew_triggered()
+ \printuntil }
+
+ \c current_file is a global variable containing the file presently
+ being edited.
+ It is defined in the private part of notepad.h:
+
+ \quotefromfile tutorials/notepad/notepad.h
+ \skipto private:
+ \printuntil currentFile;
+
+ \c clear() clears the text buffer.
+
+ \section2 Opening a file
+
+ In \c notepad.ui, right click on \c actionOpen and select \c {Go to
+ slot}
+
+ Complete method \c on_actionOpen_triggered().
+
+ \quotefromfile tutorials/notepad/notepad.cpp
+ \skipto on_actionOpen_triggered()
+ \printuntil file.close
+ \printuntil }
+
+
+ \c QFileDialog::getOpenFileName opens a dialog enabling you to select
+ a file. QFile object \c myfile has the selected \c file_name as
+ parameter. We store the selected file also into the global variable
+ \c current_file for later purposes. We open the file with \c file.open
+ as a readonly text file. If it cannot be opened, a warning is issued,
+ and the program stops.
+
+ We define a QTextStream \c instream for parameter \c myfile.
+ The contents of file \c myfile is copied into QString \a text.
+ \c setText(text) fille the buffer of our editor with \c text.
+
+ \c section2 Saving a file
+
+ We create the method for saving a file in the same way as for
+ \l {Opening a file}, by right clicking on \c actionSave, and
+ selecting \c {Go to Slot}.
+
+ \skipto Notepad::on_actionSave_triggered
+ \printuntil file.close
+ \printuntil }
+
+ QFile object \c myfile is linked to global variable \c current_file,
+ the variable that contains the file we were working with.
+ If we cannot open \c myfile, an error message is issued and the
+ method stops. We create a QTextStream \c outstream. The contents
+ of the editor buffer is converted to plain text, and then written
+ to \c outstream.
+
+ \section2 Saving a file with \c {Save as}
+
+ \skipto Notepad::on_actionSave_as_triggered
+ \printuntil file.close
+ \printuntil }
+
+ This is the same procedure as for \c {Saving a file}, the only
+ difference being that here you need to enter a new file name for
+ the file to be created.
+
+
+ \section2 Print a File
+
+ If you want to use print functionalities, you need to add
+ \c printsupport to the project file:
+
+ \badcode
+ QT += printsupport
+ \endcode
+
+ We declare a QPrinter object called \c printer.
+ We launch a printer dialog box and store the selected printer in
+ object \c printer. If we clicked on \c Cancel and did not select
+ a printer, the methods returns. The actual printer command is given
+ with \a ui->textEdit->print with our QPrinter object as parameter.
+
+ \section2 Select a Font
+
+ \skipto Notepad::on_actionFont_triggered
+ \printuntil ui->textEdit->setFont
+ \printline }
+
+ We declare a boolean indicating if we did select a font with
+ QFontDialog. If so, we set the font with \c ui->textEdit->setFont(myfont).
+
+ \section2 Copy, Cut, Paste, Undo, and Redo
+
+ If you select some text, and want to copy it to the clipboard,
+ you call the appropriate method of ui->textEdit. The same counts
+ for cut, paste, undo, and redo.
+
+ This table shows the method name to use.
+
+ \table
+ \header
+ \li Task
+ \li Method called
+ \row
+ \li Copy
+ \li ui->textEdit->copy()
+ \row
+ \li Cut
+ \li ui->textEdit->cut()
+ \row
+ \li Paste
+ \li ui->textEdit->paste()
+ \row
+ \li Undo
+ \li ui->textEdit->undo()
+ \row
+ \li Redo
+ \li ui->textEdit->redo()
+ \endtable
+
+ \b{Learn More}
+
+ \table
+ \header
+ \li About
+ \li Here
+ \row
+ \li MDI applications
+ \li QMdiArea,
+ \l{MDI Example}
+ \row
+ \li Files and I/O devices
+ \li QFile, QIODevice
+ \row
+ \li tr() and internationalization
+ \li \l{Qt Linguist Manual},
+ \l{Writing Source Code for Translation},
+ \l{Internationalization with Qt}
+ \endtable
+
+ \section1 Building and Running Notepad
+
+ Now that you have all the necessary files, select \b Build >
+ \b {Build Project Notepad} to build and run the application. Qt
+ Creator uses \c qmake and \c make to create an executable in the
+ directory specified in the build settings of the project and runs
+ it.
+
+ \section2 Building and Running from the Command Line
+
+ To build the application from the command line, switch to the
+ directory in which you have the \c .cpp file of the application
+ and add the project file (suffixed .pro) described earlier. The
+ following shell commands then build the application:
+
+ \badcode
+ qmake
+ make (or nmake on Windows)
+ \endcode
+
+ The commands create an executable in the project directory. The
+ \c qmake tool reads the project file and produces a \c Makefile
+ with instructions on how to build the application.
+ The \c make tool (or the \c nmake tool) then reads the \c Makefile
+ and produces the executable binary.
+*/
diff --git a/examples/widgets/tutorials/modelview/1_readonly/1_readonly.pro b/examples/widgets/tutorials/modelview/1_readonly/1_readonly.pro
index 72a74bbbac..18cb65d1ec 100644
--- a/examples/widgets/tutorials/modelview/1_readonly/1_readonly.pro
+++ b/examples/widgets/tutorials/modelview/1_readonly/1_readonly.pro
@@ -3,6 +3,7 @@ TARGET = mv_readonly
TEMPLATE = app
QT += widgets
+requires(qtConfig(tableview))
SOURCES += main.cpp \
mymodel.cpp
diff --git a/examples/widgets/tutorials/modelview/2_formatting/2_formatting.pro b/examples/widgets/tutorials/modelview/2_formatting/2_formatting.pro
index 8bf556f73b..590db82c93 100644
--- a/examples/widgets/tutorials/modelview/2_formatting/2_formatting.pro
+++ b/examples/widgets/tutorials/modelview/2_formatting/2_formatting.pro
@@ -3,6 +3,7 @@ TARGET = mv_formatting
TEMPLATE = app
QT += widgets
+requires(qtConfig(tableview))
SOURCES += main.cpp \
mymodel.cpp
diff --git a/examples/widgets/tutorials/modelview/3_changingmodel/3_changingmodel.pro b/examples/widgets/tutorials/modelview/3_changingmodel/3_changingmodel.pro
index 24c790d3a1..1ac36808e7 100644
--- a/examples/widgets/tutorials/modelview/3_changingmodel/3_changingmodel.pro
+++ b/examples/widgets/tutorials/modelview/3_changingmodel/3_changingmodel.pro
@@ -3,6 +3,7 @@ TARGET = mv_changingmodel
TEMPLATE = app
QT += widgets
+requires(qtConfig(tableview))
SOURCES += main.cpp \
mymodel.cpp
diff --git a/examples/widgets/tutorials/modelview/4_headers/4_headers.pro b/examples/widgets/tutorials/modelview/4_headers/4_headers.pro
index 354c39319c..0aae599de0 100644
--- a/examples/widgets/tutorials/modelview/4_headers/4_headers.pro
+++ b/examples/widgets/tutorials/modelview/4_headers/4_headers.pro
@@ -3,6 +3,7 @@ TARGET = mv_headers
TEMPLATE = app
QT += widgets
+requires(qtConfig(tableview))
SOURCES += main.cpp \
mymodel.cpp
diff --git a/examples/widgets/tutorials/modelview/5_edit/5_edit.pro b/examples/widgets/tutorials/modelview/5_edit/5_edit.pro
index 957f6e701a..b8ac19e140 100644
--- a/examples/widgets/tutorials/modelview/5_edit/5_edit.pro
+++ b/examples/widgets/tutorials/modelview/5_edit/5_edit.pro
@@ -3,6 +3,7 @@ TARGET = mv_edit
TEMPLATE = app
QT += widgets
+requires(qtConfig(tableview))
SOURCES += main.cpp \
mainwindow.cpp \
diff --git a/examples/widgets/tutorials/modelview/6_treeview/6_treeview.pro b/examples/widgets/tutorials/modelview/6_treeview/6_treeview.pro
index cbcd3eed5e..84190d0663 100644
--- a/examples/widgets/tutorials/modelview/6_treeview/6_treeview.pro
+++ b/examples/widgets/tutorials/modelview/6_treeview/6_treeview.pro
@@ -1,6 +1,7 @@
TARGET = mv_tree
TEMPLATE = app
QT += widgets
+requires(qtConfig(treeview))
SOURCES += main.cpp \
mainwindow.cpp
HEADERS += mainwindow.h
diff --git a/examples/widgets/tutorials/modelview/7_selections/7_selections.pro b/examples/widgets/tutorials/modelview/7_selections/7_selections.pro
index 24065d39a7..78ddd8e409 100644
--- a/examples/widgets/tutorials/modelview/7_selections/7_selections.pro
+++ b/examples/widgets/tutorials/modelview/7_selections/7_selections.pro
@@ -1,6 +1,7 @@
TARGET = mv_selections
TEMPLATE = app
QT += widgets
+requires(qtConfig(treeview))
SOURCES += main.cpp \
mainwindow.cpp
HEADERS += mainwindow.h
diff --git a/examples/widgets/tutorials/notepad/images/copy.png b/examples/widgets/tutorials/notepad/images/copy.png
new file mode 100644
index 0000000000..cb3442c04c
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/copy.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/create.png b/examples/widgets/tutorials/notepad/images/create.png
new file mode 100644
index 0000000000..fdfd4b438a
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/create.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/cut.png b/examples/widgets/tutorials/notepad/images/cut.png
new file mode 100644
index 0000000000..74b15301ff
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/cut.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/edit_redo.png b/examples/widgets/tutorials/notepad/images/edit_redo.png
new file mode 100644
index 0000000000..8a7725463c
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/edit_redo.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/edit_undo.png b/examples/widgets/tutorials/notepad/images/edit_undo.png
new file mode 100644
index 0000000000..852f5e3b29
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/edit_undo.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/exit.png b/examples/widgets/tutorials/notepad/images/exit.png
new file mode 100644
index 0000000000..677d4deef2
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/exit.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/font.png b/examples/widgets/tutorials/notepad/images/font.png
new file mode 100644
index 0000000000..925e501c03
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/font.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/info.png b/examples/widgets/tutorials/notepad/images/info.png
new file mode 100644
index 0000000000..9731212c4f
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/info.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/new.png b/examples/widgets/tutorials/notepad/images/new.png
new file mode 100644
index 0000000000..b24edc5d0c
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/new.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/open.png b/examples/widgets/tutorials/notepad/images/open.png
new file mode 100644
index 0000000000..7b052edf5a
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/open.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/paste.png b/examples/widgets/tutorials/notepad/images/paste.png
new file mode 100644
index 0000000000..c50dbd95b2
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/paste.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/pencil.png b/examples/widgets/tutorials/notepad/images/pencil.png
new file mode 100644
index 0000000000..a9c5e5482a
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/pencil.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/print.png b/examples/widgets/tutorials/notepad/images/print.png
new file mode 100644
index 0000000000..0cd3f28bd8
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/print.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/save.png b/examples/widgets/tutorials/notepad/images/save.png
new file mode 100644
index 0000000000..e65a29d5f1
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/save.png
Binary files differ
diff --git a/examples/widgets/tutorials/notepad/images/save_as.png b/examples/widgets/tutorials/notepad/images/save_as.png
new file mode 100644
index 0000000000..6040574322
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/images/save_as.png
Binary files differ
diff --git a/examples/widgets/dialogs/configdialog/main.cpp b/examples/widgets/tutorials/notepad/main.cpp
index e73474b866..20bcdaa7df 100644
--- a/examples/widgets/dialogs/configdialog/main.cpp
+++ b/examples/widgets/tutorials/notepad/main.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the examples of the Qt Toolkit.
+** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
@@ -48,16 +48,14 @@
**
****************************************************************************/
+#include "notepad.h"
#include <QApplication>
-#include "configdialog.h"
-
int main(int argc, char *argv[])
{
- Q_INIT_RESOURCE(configdialog);
+ QApplication EditorApp(argc, argv);
+ Notepad Editor;
+ Editor.show();
- QApplication app(argc, argv);
- app.setApplicationDisplayName("Qt Example");
- ConfigDialog dialog;
- return dialog.exec();
+ return EditorApp.exec();
}
diff --git a/examples/widgets/tutorials/notepad/notepad.cpp b/examples/widgets/tutorials/notepad/notepad.cpp
new file mode 100644
index 0000000000..44d8597cb7
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/notepad.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation 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$
+**
+****************************************************************************/
+
+#include <QFile>
+#include <QFileDialog>
+#include <QTextStream>
+#include <QMessageBox>
+#if defined(QT_PRINTSUPPORT_LIB)
+#include <QtPrintSupport/qtprintsupportglobal.h>
+#if QT_CONFIG(printer)
+#if QT_CONFIG(printdialog)
+#include <QPrintDialog>
+#endif // QT_CONFIG(printdialog)
+#include <QPrinter>
+#endif // QT_CONFIG(printer)
+#endif // QT_PRINTSUPPORT_LIB
+#include <QFont>
+#include <QFontDialog>
+
+#include "notepad.h"
+#include "ui_notepad.h"
+
+Notepad::Notepad(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::Notepad)
+{
+ ui->setupUi(this);
+ this->setCentralWidget(ui->textEdit);
+}
+
+Notepad::~Notepad()
+{
+ delete ui;
+}
+
+void Notepad::on_actionNew_triggered()
+{
+ currentFile.clear();
+ ui->textEdit->setText(QString());
+}
+
+void Notepad::on_actionOpen_triggered()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, "Open the file");
+ QFile file(fileName);
+ currentFile = fileName;
+ if (!file.open(QIODevice::ReadOnly | QFile::Text)) {
+ QMessageBox::warning(this, "Warning", "Cannot open file: " + file.errorString());
+ return;
+ }
+ setWindowTitle(fileName);
+ QTextStream in(&file);
+ QString text = in.readAll();
+ ui->textEdit->setText(text);
+ file.close();
+}
+
+void Notepad::on_actionSave_triggered()
+{
+ QString fileName;
+ // If we don't have a filename from before, get one.
+ if (currentFile.isEmpty()) {
+ fileName = QFileDialog::getSaveFileName(this, "Save");
+ currentFile = fileName;
+ } else {
+ fileName = currentFile;
+ }
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly | QFile::Text)) {
+ QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
+ return;
+ }
+ setWindowTitle(fileName);
+ QTextStream out(&file);
+ QString text = ui->textEdit->toPlainText();
+ out << text;
+ file.close();
+}
+
+void Notepad::on_actionSave_as_triggered()
+{
+ QString fileName = QFileDialog::getSaveFileName(this, "Save as");
+ QFile file(fileName);
+
+ if (!file.open(QFile::WriteOnly | QFile::Text)) {
+ QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString());
+ return;
+ }
+ currentFile = fileName;
+ setWindowTitle(fileName);
+ QTextStream out(&file);
+ QString text = ui->textEdit->toPlainText();
+ out << text;
+ file.close();
+}
+
+void Notepad::on_actionPrint_triggered()
+{
+#if QT_CONFIG(printer)
+ QPrinter printDev;
+#if QT_CONFIG(printdialog)
+ QPrintDialog dialog(&printDev, this);
+ if (dialog.exec() == QDialog::Rejected)
+ return;
+#endif // QT_CONFIG(printdialog)
+ ui->textEdit->print(&printDev);
+#endif // QT_CONFIG(printer)
+}
+
+void Notepad::on_actionExit_triggered()
+{
+ QCoreApplication::quit();
+}
+
+void Notepad::on_actionCopy_triggered()
+{
+ ui->textEdit->copy();
+}
+
+void Notepad::on_actionCut_triggered()
+{
+ ui->textEdit->cut();
+}
+
+void Notepad::on_actionPaste_triggered()
+{
+ ui->textEdit->paste();
+}
+
+void Notepad::on_actionUndo_triggered()
+{
+ ui->textEdit->undo();
+}
+
+void Notepad::on_actionRedo_triggered()
+{
+ ui->textEdit->redo();
+}
+
+void Notepad::on_actionFont_triggered()
+{
+ bool fontSelected;
+ QFont font = QFontDialog::getFont(&fontSelected, this);
+ if (fontSelected)
+ ui->textEdit->setFont(font);
+}
diff --git a/examples/widgets/tutorials/notepad/notepad.h b/examples/widgets/tutorials/notepad/notepad.h
new file mode 100644
index 0000000000..f688df45ac
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/notepad.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation 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$
+**
+****************************************************************************/
+
+#ifndef NOTEPAD_H
+#define NOTEPAD_H
+
+//! [all]
+//! [1]
+#include <QMainWindow>
+//! [1]
+
+//! [2]
+QT_BEGIN_NAMESPACE
+namespace Ui {
+class Notepad;
+}
+QT_END_NAMESPACE
+//! [2]
+
+//! [3]
+class Notepad : public QMainWindow
+{
+ Q_OBJECT
+//! [3]
+
+//! [4]
+public:
+ explicit Notepad(QWidget *parent = 0);
+//! [4]
+//! [5]
+ ~Notepad();
+//! [5]
+
+private slots:
+ void on_actionNew_triggered();
+
+ void on_actionOpen_triggered();
+
+ void on_actionSave_triggered();
+
+ void on_actionSave_as_triggered();
+
+ void on_actionPrint_triggered();
+
+ void on_actionExit_triggered();
+
+ void on_actionCopy_triggered();
+
+ void on_actionCut_triggered();
+
+ void on_actionPaste_triggered();
+
+ void on_actionUndo_triggered();
+
+ void on_actionRedo_triggered();
+
+ void on_actionFont_triggered();
+
+//! [6]
+private:
+ Ui::Notepad *ui;
+ QString currentFile;
+//! [6]
+};
+//! [all]
+
+#endif // NOTEPAD_H
diff --git a/examples/widgets/tutorials/notepad/notepad.pro b/examples/widgets/tutorials/notepad/notepad.pro
new file mode 100644
index 0000000000..6451f22735
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/notepad.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+TARGET = notepad
+
+qtHaveModule(printsupport): QT += printsupport
+requires(qtConfig(fontdialog))
+
+SOURCES += \
+ main.cpp\
+ notepad.cpp
+
+HEADERS += notepad.h
+
+FORMS += notepad.ui
+
+RESOURCES += \
+ notepad.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/notepad
+INSTALLS += target
+
diff --git a/examples/widgets/tutorials/notepad/notepad.qrc b/examples/widgets/tutorials/notepad/notepad.qrc
new file mode 100644
index 0000000000..ec11679f13
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/notepad.qrc
@@ -0,0 +1,19 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/copy.png</file>
+ <file>images/create.png</file>
+ <file>images/cut.png</file>
+ <file>images/edit_redo.png</file>
+ <file>images/edit_undo.png</file>
+ <file>images/exit.png</file>
+ <file>images/font.png</file>
+ <file>images/info.png</file>
+ <file>images/new.png</file>
+ <file>images/open.png</file>
+ <file>images/paste.png</file>
+ <file>images/pencil.png</file>
+ <file>images/print.png</file>
+ <file>images/save.png</file>
+ <file>images/save_as.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/widgets/tutorials/notepad/notepad.ui b/examples/widgets/tutorials/notepad/notepad.ui
new file mode 100644
index 0000000000..d197a95fe7
--- /dev/null
+++ b/examples/widgets/tutorials/notepad/notepad.ui
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Notepad</class>
+ <widget class="QMainWindow" name="Notepad">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>524</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Notepad</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTextEdit" name="textEdit"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>524</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFile">
+ <property name="title">
+ <string>File</string>
+ </property>
+ <addaction name="actionNew"/>
+ <addaction name="actionOpen"/>
+ <addaction name="actionSave"/>
+ <addaction name="actionSave_as"/>
+ <addaction name="actionPrint"/>
+ <addaction name="separator"/>
+ <addaction name="actionExit"/>
+ </widget>
+ <widget class="QMenu" name="menuEdit">
+ <property name="title">
+ <string>Edit</string>
+ </property>
+ <addaction name="actionCopy"/>
+ <addaction name="actionCut"/>
+ <addaction name="actionPaste"/>
+ <addaction name="separator"/>
+ <addaction name="actionUndo"/>
+ <addaction name="actionRedo"/>
+ <addaction name="actionFont"/>
+ </widget>
+ <addaction name="menuFile"/>
+ <addaction name="menuEdit"/>
+ </widget>
+ <widget class="QToolBar" name="mainToolBar">
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="actionNew"/>
+ <addaction name="actionOpen"/>
+ <addaction name="actionSave"/>
+ <addaction name="actionSave_as"/>
+ <addaction name="actionPrint"/>
+ <addaction name="separator"/>
+ <addaction name="actionCopy"/>
+ <addaction name="actionCut"/>
+ <addaction name="actionPaste"/>
+ <addaction name="actionUndo"/>
+ <addaction name="actionRedo"/>
+ <addaction name="actionFont"/>
+ <addaction name="separator"/>
+ <addaction name="actionExit"/>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <action name="actionNew">
+ <property name="icon">
+ <iconset resource="notepad.qrc">
+ <normaloff>:/images/new.png</normaloff>:/images/new.png</iconset>
+ </property>
+ <property name="text">
+ <string>New</string>
+ </property>
+ </action>
+ <action name="actionOpen">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/open.png</normaloff>:/images/open.png</iconset>
+ </property>
+ <property name="text">
+ <string>Open</string>
+ </property>
+ </action>
+ <action name="actionSave">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/save.png</normaloff>:/images/save.png</iconset>
+ </property>
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </action>
+ <action name="actionSave_as">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/save_as.png</normaloff>:/images/save_as.png</iconset>
+ </property>
+ <property name="text">
+ <string>Save as</string>
+ </property>
+ </action>
+ <action name="actionPrint">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/print.png</normaloff>:/images/print.png</iconset>
+ </property>
+ <property name="text">
+ <string>Print</string>
+ </property>
+ </action>
+ <action name="actionExit">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/exit.png</normaloff>:/images/exit.png</iconset>
+ </property>
+ <property name="text">
+ <string>Exit</string>
+ </property>
+ </action>
+ <action name="actionCopy">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/copy.png</normaloff>:/images/copy.png</iconset>
+ </property>
+ <property name="text">
+ <string>Copy</string>
+ </property>
+ </action>
+ <action name="actionCut">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/cut.png</normaloff>:/images/cut.png</iconset>
+ </property>
+ <property name="text">
+ <string>Cut</string>
+ </property>
+ </action>
+ <action name="actionPaste">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/paste.png</normaloff>:/images/paste.png</iconset>
+ </property>
+ <property name="text">
+ <string>Paste</string>
+ </property>
+ </action>
+ <action name="actionUndo">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/edit_undo.png</normaloff>:/images/edit_undo.png</iconset>
+ </property>
+ <property name="text">
+ <string>Undo</string>
+ </property>
+ </action>
+ <action name="actionRedo">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/edit_redo.png</normaloff>:/images/edit_redo.png</iconset>
+ </property>
+ <property name="text">
+ <string>Redo</string>
+ </property>
+ </action>
+ <action name="actionFont">
+ <property name="icon">
+ <iconset>
+ <normaloff>:/images/font.png</normaloff>:/images/font.png</iconset>
+ </property>
+ <property name="text">
+ <string>Font</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+ <include location="notepad.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/examples/widgets/tutorials/tutorials.pro b/examples/widgets/tutorials/tutorials.pro
index 2eb87cdbd5..0aaa119d8f 100644
--- a/examples/widgets/tutorials/tutorials.pro
+++ b/examples/widgets/tutorials/tutorials.pro
@@ -1,2 +1,2 @@
TEMPLATE = subdirs
-SUBDIRS += addressbook widgets modelview gettingStarted
+SUBDIRS += addressbook widgets modelview gettingStarted notepad
diff --git a/examples/widgets/tutorials/widgets/nestedlayouts/nestedlayouts.pro b/examples/widgets/tutorials/widgets/nestedlayouts/nestedlayouts.pro
index 33ee6e6cb0..d47fb15eef 100644
--- a/examples/widgets/tutorials/widgets/nestedlayouts/nestedlayouts.pro
+++ b/examples/widgets/tutorials/widgets/nestedlayouts/nestedlayouts.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(tableview))
SOURCES = main.cpp
diff --git a/examples/widgets/widgets/calendarwidget/calendarwidget.pro b/examples/widgets/widgets/calendarwidget/calendarwidget.pro
index a60f10bf36..4d130a48a1 100644
--- a/examples/widgets/widgets/calendarwidget/calendarwidget.pro
+++ b/examples/widgets/widgets/calendarwidget/calendarwidget.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = window.h
SOURCES = main.cpp \
diff --git a/examples/widgets/widgets/charactermap/charactermap.pro b/examples/widgets/widgets/charactermap/charactermap.pro
index 0450940c22..373aabca73 100644
--- a/examples/widgets/widgets/charactermap/charactermap.pro
+++ b/examples/widgets/widgets/charactermap/charactermap.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = characterwidget.h \
mainwindow.h
diff --git a/examples/widgets/widgets/elidedlabel/elidedlabel.pro b/examples/widgets/widgets/elidedlabel/elidedlabel.pro
index 1c135ed9c3..34040c92af 100644
--- a/examples/widgets/widgets/elidedlabel/elidedlabel.pro
+++ b/examples/widgets/widgets/elidedlabel/elidedlabel.pro
@@ -1,6 +1,7 @@
# Nokia Qt Examples: elided label example
QT += core gui widgets
+requires(qtConfig(combobox))
TARGET = elidedlabel
TEMPLATE = app
diff --git a/examples/widgets/widgets/icons/icons.pro b/examples/widgets/widgets/icons/icons.pro
index 450bdf9f8a..243ce6b092 100644
--- a/examples/widgets/widgets/icons/icons.pro
+++ b/examples/widgets/widgets/icons/icons.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = iconpreviewarea.h \
iconsizespinbox.h \
diff --git a/examples/widgets/widgets/imageviewer/imageviewer.pro b/examples/widgets/widgets/imageviewer/imageviewer.pro
index 4903a68537..d3db63ec20 100644
--- a/examples/widgets/widgets/imageviewer/imageviewer.pro
+++ b/examples/widgets/widgets/imageviewer/imageviewer.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
qtHaveModule(printsupport): QT += printsupport
HEADERS = imageviewer.h
diff --git a/examples/widgets/widgets/lineedits/lineedits.pro b/examples/widgets/widgets/lineedits/lineedits.pro
index 0ab994ea11..71f0e3e681 100644
--- a/examples/widgets/widgets/lineedits/lineedits.pro
+++ b/examples/widgets/widgets/lineedits/lineedits.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = window.h
SOURCES = main.cpp \
diff --git a/examples/widgets/widgets/movie/movie.pro b/examples/widgets/widgets/movie/movie.pro
index e3b9b5129c..f9f89109e4 100644
--- a/examples/widgets/widgets/movie/movie.pro
+++ b/examples/widgets/widgets/movie/movie.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = movieplayer.h
SOURCES = main.cpp \
diff --git a/examples/widgets/widgets/scribble/scribble.pro b/examples/widgets/widgets/scribble/scribble.pro
index aff0fb442c..56caaaf8e6 100644
--- a/examples/widgets/widgets/scribble/scribble.pro
+++ b/examples/widgets/widgets/scribble/scribble.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
qtHaveModule(printsupport): QT += printsupport
HEADERS = mainwindow.h \
diff --git a/examples/widgets/widgets/sliders/sliders.pro b/examples/widgets/widgets/sliders/sliders.pro
index 40c3167eea..963331779c 100644
--- a/examples/widgets/widgets/sliders/sliders.pro
+++ b/examples/widgets/widgets/sliders/sliders.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = slidersgroup.h \
window.h
diff --git a/examples/widgets/widgets/spinboxes/spinboxes.pro b/examples/widgets/widgets/spinboxes/spinboxes.pro
index 67fc9e2d34..832c3725c5 100644
--- a/examples/widgets/widgets/spinboxes/spinboxes.pro
+++ b/examples/widgets/widgets/spinboxes/spinboxes.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(datetimeedit))
HEADERS = window.h
SOURCES = main.cpp \
diff --git a/examples/widgets/widgets/styles/styles.pro b/examples/widgets/widgets/styles/styles.pro
index 235642f270..87dee7e04c 100644
--- a/examples/widgets/widgets/styles/styles.pro
+++ b/examples/widgets/widgets/styles/styles.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = norwegianwoodstyle.h \
widgetgallery.h
diff --git a/examples/widgets/widgets/stylesheet/stylesheet.pro b/examples/widgets/widgets/stylesheet/stylesheet.pro
index 7607006fad..0fe3187f63 100644
--- a/examples/widgets/widgets/stylesheet/stylesheet.pro
+++ b/examples/widgets/widgets/stylesheet/stylesheet.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
HEADERS = mainwindow.h \
stylesheeteditor.h
diff --git a/examples/widgets/widgets/tablet/mainwindow.cpp b/examples/widgets/widgets/tablet/mainwindow.cpp
index 0d63ac316b..feae16dd83 100644
--- a/examples/widgets/widgets/tablet/mainwindow.cpp
+++ b/examples/widgets/widgets/tablet/mainwindow.cpp
@@ -60,6 +60,7 @@ MainWindow::MainWindow(TabletCanvas *canvas)
createMenus();
setWindowTitle(tr("Tablet Example"));
setCentralWidget(m_canvas);
+ QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
}
//! [0]
@@ -97,6 +98,11 @@ void MainWindow::setSaturationValuator(QAction *action)
}
//! [4]
+void MainWindow::setEventCompression(bool compress)
+{
+ QCoreApplication::setAttribute(Qt::AA_CompressTabletEvents, compress);
+}
+
//! [5]
void MainWindow::save()
{
@@ -220,6 +226,10 @@ void MainWindow::createMenus()
connect(colorSaturationGroup, &QActionGroup::triggered,
this, &MainWindow::setSaturationValuator);
+ QAction *compressAction = tabletMenu->addAction(tr("Co&mpress events"));
+ compressAction->setCheckable(true);
+ connect(compressAction, &QAction::toggled, this, &MainWindow::setEventCompression);
+
QMenu *helpMenu = menuBar()->addMenu("&Help");
helpMenu->addAction(tr("A&bout"), this, &MainWindow::about);
helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
diff --git a/examples/widgets/widgets/tablet/mainwindow.h b/examples/widgets/widgets/tablet/mainwindow.h
index 68af1f1687..4b99324f04 100644
--- a/examples/widgets/widgets/tablet/mainwindow.h
+++ b/examples/widgets/widgets/tablet/mainwindow.h
@@ -71,6 +71,7 @@ private slots:
void setAlphaValuator(QAction *action);
void setLineWidthValuator(QAction *action);
void setSaturationValuator(QAction *action);
+ void setEventCompression(bool compress);
void save();
void load();
void about();
diff --git a/examples/widgets/widgets/tablet/tablet.pro b/examples/widgets/widgets/tablet/tablet.pro
index 9b8927f483..5772cd0385 100644
--- a/examples/widgets/widgets/tablet/tablet.pro
+++ b/examples/widgets/widgets/tablet/tablet.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(filedialog))
HEADERS = mainwindow.h \
tabletcanvas.h \
diff --git a/examples/widgets/widgets/tablet/tabletcanvas.cpp b/examples/widgets/widgets/tablet/tabletcanvas.cpp
index 90b3222970..4b11568dfe 100644
--- a/examples/widgets/widgets/tablet/tabletcanvas.cpp
+++ b/examples/widgets/widgets/tablet/tabletcanvas.cpp
@@ -65,21 +65,9 @@ TabletCanvas::TabletCanvas()
, m_deviceDown(false)
{
resize(500, 500);
- initPixmap();
setAutoFillBackground(true);
setAttribute(Qt::WA_TabletTracking);
}
-
-void TabletCanvas::initPixmap()
-{
- QPixmap newPixmap = QPixmap(width(), height());
- newPixmap.fill(Qt::white);
- QPainter painter(&newPixmap);
- if (!m_pixmap.isNull())
- painter.drawPixmap(0, 0, m_pixmap);
- painter.end();
- m_pixmap = newPixmap;
-}
//! [0]
//! [1]
@@ -105,23 +93,26 @@ bool TabletCanvas::loadImage(const QString &file)
//! [3]
void TabletCanvas::tabletEvent(QTabletEvent *event)
{
-
switch (event->type()) {
case QEvent::TabletPress:
if (!m_deviceDown) {
m_deviceDown = true;
lastPoint.pos = event->posF();
+ lastPoint.pressure = event->pressure();
lastPoint.rotation = event->rotation();
}
break;
case QEvent::TabletMove:
+#ifndef Q_OS_IOS
if (event->device() == QTabletEvent::RotationStylus)
updateCursor(event);
+#endif
if (m_deviceDown) {
updateBrush(event);
QPainter painter(&m_pixmap);
paintPixmap(painter, event);
lastPoint.pos = event->posF();
+ lastPoint.pressure = event->pressure();
lastPoint.rotation = event->rotation();
}
break;
@@ -138,8 +129,23 @@ void TabletCanvas::tabletEvent(QTabletEvent *event)
//! [3]
//! [4]
+void TabletCanvas::initPixmap()
+{
+ qreal dpr = devicePixelRatioF();
+ QPixmap newPixmap = QPixmap(width() * dpr, height() * dpr);
+ newPixmap.setDevicePixelRatio(dpr);
+ newPixmap.fill(Qt::white);
+ QPainter painter(&newPixmap);
+ if (!m_pixmap.isNull())
+ painter.drawPixmap(0, 0, m_pixmap);
+ painter.end();
+ m_pixmap = newPixmap;
+}
+
void TabletCanvas::paintEvent(QPaintEvent *)
{
+ if (m_pixmap.isNull())
+ initPixmap();
QPainter painter(this);
painter.drawPixmap(0, 0, m_pixmap);
}
@@ -171,13 +177,14 @@ void TabletCanvas::paintPixmap(QPainter &painter, QTabletEvent *event)
painter.setPen(Qt::NoPen);
painter.setBrush(m_brush);
QPolygonF poly;
- qreal halfWidth = m_pen.widthF();
- QPointF brushAdjust(qSin(qDegreesToRadians(lastPoint.rotation)) * halfWidth,
- qCos(qDegreesToRadians(lastPoint.rotation)) * halfWidth);
+ qreal halfWidth = pressureToWidth(lastPoint.pressure);
+ QPointF brushAdjust(qSin(qDegreesToRadians(-lastPoint.rotation)) * halfWidth,
+ qCos(qDegreesToRadians(-lastPoint.rotation)) * halfWidth);
poly << lastPoint.pos + brushAdjust;
poly << lastPoint.pos - brushAdjust;
- brushAdjust = QPointF(qSin(qDegreesToRadians(event->rotation())) * halfWidth,
- qCos(qDegreesToRadians(event->rotation())) * halfWidth);
+ halfWidth = m_pen.widthF();
+ brushAdjust = QPointF(qSin(qDegreesToRadians(-event->rotation())) * halfWidth,
+ qCos(qDegreesToRadians(-event->rotation())) * halfWidth);
poly << event->posF() - brushAdjust;
poly << event->posF() + brushAdjust;
painter.drawConvexPolygon(poly);
@@ -215,6 +222,11 @@ void TabletCanvas::paintPixmap(QPainter &painter, QTabletEvent *event)
}
//! [5]
+qreal TabletCanvas::pressureToWidth(qreal pressure)
+{
+ return pressure * 10 + 1;
+}
+
//! [7]
void TabletCanvas::updateBrush(const QTabletEvent *event)
{
@@ -260,7 +272,7 @@ void TabletCanvas::updateBrush(const QTabletEvent *event)
//! [9] //! [10]
switch (m_lineWidthValuator) {
case PressureValuator:
- m_pen.setWidthF(event->pressure() * 10 + 1);
+ m_pen.setWidthF(pressureToWidth(event->pressure()));
break;
case TiltValuator:
m_pen.setWidthF(maximum(abs(vValue - 127), abs(hValue - 127)) / 12);
@@ -305,7 +317,7 @@ void TabletCanvas::updateCursor(const QTabletEvent *event)
QPainter painter(&img);
QTransform transform = painter.transform();
transform.translate(16, 16);
- transform.rotate(-event->rotation());
+ transform.rotate(event->rotation());
painter.setTransform(transform);
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
painter.drawImage(-24, -24, origImg);
diff --git a/examples/widgets/widgets/tablet/tabletcanvas.h b/examples/widgets/widgets/tablet/tabletcanvas.h
index 1784e05916..a1b31c65bf 100644
--- a/examples/widgets/widgets/tablet/tabletcanvas.h
+++ b/examples/widgets/widgets/tablet/tabletcanvas.h
@@ -103,6 +103,7 @@ private:
void initPixmap();
void paintPixmap(QPainter &painter, QTabletEvent *event);
Qt::BrushStyle brushPattern(qreal value);
+ qreal pressureToWidth(qreal pressure);
void updateBrush(const QTabletEvent *event);
void updateCursor(const QTabletEvent *event);
@@ -117,6 +118,7 @@ private:
struct Point {
QPointF pos;
+ qreal pressure;
qreal rotation;
} lastPoint;
};
diff --git a/examples/widgets/widgets/tetrix/main.cpp b/examples/widgets/widgets/tetrix/main.cpp
index 886e94de7c..2698190e76 100644
--- a/examples/widgets/widgets/tetrix/main.cpp
+++ b/examples/widgets/widgets/tetrix/main.cpp
@@ -59,6 +59,5 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
TetrixWindow window;
window.show();
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
return app.exec();
}
diff --git a/examples/widgets/widgets/tetrix/tetrixpiece.cpp b/examples/widgets/widgets/tetrix/tetrixpiece.cpp
index 69e1733ac4..3d8fa86860 100644
--- a/examples/widgets/widgets/tetrix/tetrixpiece.cpp
+++ b/examples/widgets/widgets/tetrix/tetrixpiece.cpp
@@ -57,7 +57,7 @@
//! [0]
void TetrixPiece::setRandomShape()
{
- setShape(TetrixShape(qrand() % 7 + 1));
+ setShape(TetrixShape(QRandomGenerator::global()->bounded(7) + 1));
}
//! [0]
diff --git a/examples/widgets/widgets/tooltips/main.cpp b/examples/widgets/widgets/tooltips/main.cpp
index 3c64a33a4c..8276b3dc8d 100644
--- a/examples/widgets/widgets/tooltips/main.cpp
+++ b/examples/widgets/widgets/tooltips/main.cpp
@@ -57,7 +57,6 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(tooltips);
QApplication app(argc, argv);
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
SortingBox sortingBox;
sortingBox.show();
return app.exec();
diff --git a/examples/widgets/widgets/tooltips/sortingbox.cpp b/examples/widgets/widgets/tooltips/sortingbox.cpp
index c15fdcf95b..4769a30c64 100644
--- a/examples/widgets/widgets/tooltips/sortingbox.cpp
+++ b/examples/widgets/widgets/tooltips/sortingbox.cpp
@@ -292,7 +292,7 @@ QPoint SortingBox::initialItemPosition(const QPainterPath &path)
//! [24]
QPoint SortingBox::randomItemPosition()
{
- return QPoint(qrand() % (width() - 120), qrand() % (height() - 120));
+ return QPoint(QRandomGenerator::global()->bounded(width() - 120), QRandomGenerator::global()->bounded(height() - 120));
}
//! [24]
@@ -306,6 +306,6 @@ QColor SortingBox::initialItemColor()
//! [26]
QColor SortingBox::randomItemColor()
{
- return QColor::fromHsv(qrand() % 256, 255, 190);
+ return QColor::fromHsv(QRandomGenerator::global()->bounded(256), 255, 190);
}
//! [26]
diff --git a/examples/widgets/widgets/validators/validators.pro b/examples/widgets/widgets/validators/validators.pro
index 68805f33d3..ab1eb7809b 100644
--- a/examples/widgets/widgets/validators/validators.pro
+++ b/examples/widgets/widgets/validators/validators.pro
@@ -1,4 +1,5 @@
QT += widgets
+requires(qtConfig(combobox))
FORMS += validators.ui
RESOURCES += validators.qrc
diff --git a/examples/xml/dombookmarks/dombookmarks.pro b/examples/xml/dombookmarks/dombookmarks.pro
index 07004377a0..280207eebb 100644
--- a/examples/xml/dombookmarks/dombookmarks.pro
+++ b/examples/xml/dombookmarks/dombookmarks.pro
@@ -4,6 +4,7 @@ SOURCES = main.cpp \
mainwindow.cpp \
xbeltree.cpp
QT += xml widgets
+requires(qtConfig(filedialog))
EXAMPLE_FILES = frank.xbel jennifer.xbel
diff --git a/examples/xml/dombookmarks/mainwindow.cpp b/examples/xml/dombookmarks/mainwindow.cpp
index e0f208d336..fade2dfc96 100644
--- a/examples/xml/dombookmarks/mainwindow.cpp
+++ b/examples/xml/dombookmarks/mainwindow.cpp
@@ -58,13 +58,13 @@ MainWindow::MainWindow()
xbelTree = new XbelTree;
setCentralWidget(xbelTree);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("DOM Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
void MainWindow::open()
@@ -80,8 +80,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -102,8 +102,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -119,37 +119,21 @@ void MainWindow::about()
"documents."));
}
-void MainWindow::createActions()
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
diff --git a/examples/xml/dombookmarks/mainwindow.h b/examples/xml/dombookmarks/mainwindow.h
index 6d490caf64..0a8c7bdd82 100644
--- a/examples/xml/dombookmarks/mainwindow.h
+++ b/examples/xml/dombookmarks/mainwindow.h
@@ -68,18 +68,9 @@ public slots:
void about();
private:
- void createActions();
void createMenus();
XbelTree *xbelTree;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
#endif
diff --git a/examples/xml/dombookmarks/xbeltree.cpp b/examples/xml/dombookmarks/xbeltree.cpp
index 82afc48bd9..f7ff1de638 100644
--- a/examples/xml/dombookmarks/xbeltree.cpp
+++ b/examples/xml/dombookmarks/xbeltree.cpp
@@ -52,6 +52,18 @@
#include "xbeltree.h"
+enum { DomElementRole = Qt::UserRole + 1 };
+
+Q_DECLARE_METATYPE(QDomElement)
+
+static inline QString titleElement() { return QStringLiteral("title"); }
+static inline QString folderElement() { return QStringLiteral("folder"); }
+static inline QString bookmarkElement() { return QStringLiteral("bookmark"); }
+
+static inline QString versionAttribute() { return QStringLiteral("version"); }
+static inline QString hrefAttribute() { return QStringLiteral("href"); }
+static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
XbelTree::XbelTree(QWidget *parent)
: QTreeWidget(parent)
{
@@ -68,6 +80,24 @@ XbelTree::XbelTree(QWidget *parent)
bookmarkIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
}
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void XbelTree::contextMenuEvent(QContextMenuEvent *event)
+{
+ const QTreeWidgetItem *item = itemAt(event->pos());
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(event->globalPos());
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
bool XbelTree::read(QIODevice *device)
{
QString errorStr;
@@ -89,8 +119,8 @@ bool XbelTree::read(QIODevice *device)
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("The file is not an XBEL file."));
return false;
- } else if (root.hasAttribute("version")
- && root.attribute("version") != "1.0") {
+ } else if (root.hasAttribute(versionAttribute())
+ && root.attribute(versionAttribute()) != QLatin1String("1.0")) {
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("The file is not an XBEL version 1.0 "
"file."));
@@ -99,22 +129,20 @@ bool XbelTree::read(QIODevice *device)
clear();
- disconnect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
- this, SLOT(updateDomElement(QTreeWidgetItem*,int)));
+ disconnect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement);
- QDomElement child = root.firstChildElement("folder");
+ QDomElement child = root.firstChildElement(folderElement());
while (!child.isNull()) {
parseFolderElement(child);
- child = child.nextSiblingElement("folder");
+ child = child.nextSiblingElement(folderElement());
}
- connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
- this, SLOT(updateDomElement(QTreeWidgetItem*,int)));
+ connect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement);
return true;
}
-bool XbelTree::write(QIODevice *device)
+bool XbelTree::write(QIODevice *device) const
{
const int IndentSize = 4;
@@ -123,21 +151,21 @@ bool XbelTree::write(QIODevice *device)
return true;
}
-void XbelTree::updateDomElement(QTreeWidgetItem *item, int column)
+void XbelTree::updateDomElement(const QTreeWidgetItem *item, int column)
{
- QDomElement element = domElementForItem.value(item);
+ QDomElement element = item->data(0, DomElementRole).value<QDomElement>();
if (!element.isNull()) {
if (column == 0) {
- QDomElement oldTitleElement = element.firstChildElement("title");
- QDomElement newTitleElement = domDocument.createElement("title");
+ QDomElement oldTitleElement = element.firstChildElement(titleElement());
+ QDomElement newTitleElement = domDocument.createElement(titleElement());
QDomText newTitleText = domDocument.createTextNode(item->text(0));
newTitleElement.appendChild(newTitleText);
element.replaceChild(newTitleElement, oldTitleElement);
} else {
- if (element.tagName() == "bookmark")
- element.setAttribute("href", item->text(1));
+ if (element.tagName() == bookmarkElement())
+ element.setAttribute(hrefAttribute(), item->text(1));
}
}
}
@@ -147,7 +175,7 @@ void XbelTree::parseFolderElement(const QDomElement &element,
{
QTreeWidgetItem *item = createItem(element, parentItem);
- QString title = element.firstChildElement("title").text();
+ QString title = element.firstChildElement(titleElement()).text();
if (title.isEmpty())
title = QObject::tr("Folder");
@@ -155,25 +183,25 @@ void XbelTree::parseFolderElement(const QDomElement &element,
item->setIcon(0, folderIcon);
item->setText(0, title);
- bool folded = (element.attribute("folded") != "no");
+ bool folded = (element.attribute(foldedAttribute()) != QLatin1String("no"));
setItemExpanded(item, !folded);
QDomElement child = element.firstChildElement();
while (!child.isNull()) {
- if (child.tagName() == "folder") {
+ if (child.tagName() == folderElement()) {
parseFolderElement(child, item);
- } else if (child.tagName() == "bookmark") {
+ } else if (child.tagName() == bookmarkElement()) {
QTreeWidgetItem *childItem = createItem(child, item);
- QString title = child.firstChildElement("title").text();
+ QString title = child.firstChildElement(titleElement()).text();
if (title.isEmpty())
title = QObject::tr("Folder");
childItem->setFlags(item->flags() | Qt::ItemIsEditable);
childItem->setIcon(0, bookmarkIcon);
childItem->setText(0, title);
- childItem->setText(1, child.attribute("href"));
- } else if (child.tagName() == "separator") {
+ childItem->setText(1, child.attribute(hrefAttribute()));
+ } else if (child.tagName() == QLatin1String("separator")) {
QTreeWidgetItem *childItem = createItem(child, item);
childItem->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEditable));
childItem->setText(0, QString(30, 0xB7));
@@ -191,6 +219,6 @@ QTreeWidgetItem *XbelTree::createItem(const QDomElement &element,
} else {
item = new QTreeWidgetItem(this);
}
- domElementForItem.insert(item, element);
+ item->setData(0, DomElementRole, QVariant::fromValue(element));
return item;
}
diff --git a/examples/xml/dombookmarks/xbeltree.h b/examples/xml/dombookmarks/xbeltree.h
index bf4b55ea74..f6c7ef8bfe 100644
--- a/examples/xml/dombookmarks/xbeltree.h
+++ b/examples/xml/dombookmarks/xbeltree.h
@@ -52,7 +52,6 @@
#define XBELTREE_H
#include <QDomDocument>
-#include <QHash>
#include <QIcon>
#include <QTreeWidget>
@@ -64,10 +63,15 @@ public:
XbelTree(QWidget *parent = 0);
bool read(QIODevice *device);
- bool write(QIODevice *device);
+ bool write(QIODevice *device) const;
+
+protected:
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void contextMenuEvent(QContextMenuEvent *event) Q_DECL_OVERRIDE;
+#endif
private slots:
- void updateDomElement(QTreeWidgetItem *item, int column);
+ void updateDomElement(const QTreeWidgetItem *item, int column);
private:
void parseFolderElement(const QDomElement &element,
@@ -76,7 +80,6 @@ private:
QTreeWidgetItem *parentItem = 0);
QDomDocument domDocument;
- QHash<QTreeWidgetItem *, QDomElement> domElementForItem;
QIcon folderIcon;
QIcon bookmarkIcon;
};
diff --git a/examples/xml/rsslisting/rsslisting.pro b/examples/xml/rsslisting/rsslisting.pro
index 5997f96ca9..b6a00aa0c6 100644
--- a/examples/xml/rsslisting/rsslisting.pro
+++ b/examples/xml/rsslisting/rsslisting.pro
@@ -1,6 +1,7 @@
HEADERS += rsslisting.h
SOURCES += main.cpp rsslisting.cpp
QT += network xml widgets
+requires(qtConfig(treewidget))
# install
target.path = $$[QT_INSTALL_EXAMPLES]/xml/rsslisting
diff --git a/examples/xml/saxbookmarks/mainwindow.cpp b/examples/xml/saxbookmarks/mainwindow.cpp
index 2ce2b9a508..0583cd82cf 100644
--- a/examples/xml/saxbookmarks/mainwindow.cpp
+++ b/examples/xml/saxbookmarks/mainwindow.cpp
@@ -62,17 +62,40 @@ MainWindow::MainWindow()
treeWidget = new QTreeWidget;
treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
treeWidget->setHeaderLabels(labels);
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(treeWidget, &QWidget::customContextMenuRequested,
+ this, &MainWindow::onCustomContextMenuRequested);
+#endif
setCentralWidget(treeWidget);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("SAX Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
+{
+ const QTreeWidgetItem *item = treeWidget->itemAt(pos);
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos));
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
void MainWindow::open()
{
QString fileName =
@@ -93,8 +116,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -116,8 +139,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -134,37 +157,21 @@ void MainWindow::about()
"hand."));
}
-void MainWindow::createActions()
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
diff --git a/examples/xml/saxbookmarks/mainwindow.h b/examples/xml/saxbookmarks/mainwindow.h
index 828a0ed14e..20a11bb202 100644
--- a/examples/xml/saxbookmarks/mainwindow.h
+++ b/examples/xml/saxbookmarks/mainwindow.h
@@ -68,20 +68,13 @@ public slots:
void open();
void saveAs();
void about();
-
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void onCustomContextMenuRequested(const QPoint &pos);
+#endif
private:
- void createActions();
void createMenus();
QTreeWidget *treeWidget;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
#endif
diff --git a/examples/xml/saxbookmarks/saxbookmarks.pro b/examples/xml/saxbookmarks/saxbookmarks.pro
index d07a6e3fb8..af2a124a13 100644
--- a/examples/xml/saxbookmarks/saxbookmarks.pro
+++ b/examples/xml/saxbookmarks/saxbookmarks.pro
@@ -6,6 +6,7 @@ SOURCES = main.cpp \
xbelgenerator.cpp \
xbelhandler.cpp
QT += xml widgets
+requires(qtConfig(filedialog))
EXAMPLE_FILES = frank.xbel jennifer.xbel
diff --git a/examples/xml/saxbookmarks/xbelgenerator.cpp b/examples/xml/saxbookmarks/xbelgenerator.cpp
index 30ce1428e6..ee6f113f9c 100644
--- a/examples/xml/saxbookmarks/xbelgenerator.cpp
+++ b/examples/xml/saxbookmarks/xbelgenerator.cpp
@@ -52,7 +52,7 @@
#include "xbelgenerator.h"
-XbelGenerator::XbelGenerator(QTreeWidget *treeWidget)
+XbelGenerator::XbelGenerator(const QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
}
@@ -81,25 +81,25 @@ QString XbelGenerator::indent(int depth)
QString XbelGenerator::escapedText(const QString &str)
{
QString result = str;
- result.replace("&", "&amp;");
- result.replace("<", "&lt;");
- result.replace(">", "&gt;");
+ result.replace('&', "&amp;");
+ result.replace('<', "&lt;");
+ result.replace('>', "&gt;");
return result;
}
QString XbelGenerator::escapedAttribute(const QString &str)
{
QString result = escapedText(str);
- result.replace("\"", "&quot;");
+ result.replace(QLatin1Char('"'), "&quot;");
result.prepend(QLatin1Char('"'));
result.append(QLatin1Char('"'));
return result;
}
-void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
+void XbelGenerator::generateItem(const QTreeWidgetItem *item, int depth)
{
QString tagName = item->data(0, Qt::UserRole).toString();
- if (tagName == "folder") {
+ if (tagName == QLatin1String("folder")) {
bool folded = !treeWidget->isItemExpanded(item);
out << indent(depth) << "<folder folded=\"" << (folded ? "yes" : "no")
<< "\">\n"
@@ -110,7 +110,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
generateItem(item->child(i), depth + 1);
out << indent(depth) << "</folder>\n";
- } else if (tagName == "bookmark") {
+ } else if (tagName == QLatin1String("bookmark")) {
out << indent(depth) << "<bookmark";
if (!item->text(1).isEmpty())
out << " href=" << escapedAttribute(item->text(1));
@@ -118,7 +118,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
<< indent(depth + 1) << "<title>" << escapedText(item->text(0))
<< "</title>\n"
<< indent(depth) << "</bookmark>\n";
- } else if (tagName == "separator") {
+ } else if (tagName == QLatin1String("separator")) {
out << indent(depth) << "<separator/>\n";
}
}
diff --git a/examples/xml/saxbookmarks/xbelgenerator.h b/examples/xml/saxbookmarks/xbelgenerator.h
index 44069599e2..abfabfd75c 100644
--- a/examples/xml/saxbookmarks/xbelgenerator.h
+++ b/examples/xml/saxbookmarks/xbelgenerator.h
@@ -61,7 +61,7 @@ QT_END_NAMESPACE
class XbelGenerator
{
public:
- XbelGenerator(QTreeWidget *treeWidget);
+ explicit XbelGenerator(const QTreeWidget *treeWidget);
bool write(QIODevice *device);
@@ -69,9 +69,9 @@ private:
static QString indent(int indentLevel);
static QString escapedText(const QString &str);
static QString escapedAttribute(const QString &str);
- void generateItem(QTreeWidgetItem *item, int depth);
+ void generateItem(const QTreeWidgetItem *item, int depth);
- QTreeWidget *treeWidget;
+ const QTreeWidget *treeWidget;
QTextStream out;
};
diff --git a/examples/xml/saxbookmarks/xbelhandler.cpp b/examples/xml/saxbookmarks/xbelhandler.cpp
index 03b16c81f1..7e2a9db3c2 100644
--- a/examples/xml/saxbookmarks/xbelhandler.cpp
+++ b/examples/xml/saxbookmarks/xbelhandler.cpp
@@ -52,6 +52,10 @@
#include "xbelhandler.h"
+static inline QString versionAttribute() { return QStringLiteral("version"); }
+static inline QString hrefAttribute() { return QStringLiteral("href"); }
+static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
XbelHandler::XbelHandler(QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
@@ -72,32 +76,32 @@ bool XbelHandler::startElement(const QString & /* namespaceURI */,
const QString &qName,
const QXmlAttributes &attributes)
{
- if (!metXbelTag && qName != "xbel") {
+ if (!metXbelTag && qName != QLatin1String("xbel")) {
errorStr = QObject::tr("The file is not an XBEL file.");
return false;
}
- if (qName == "xbel") {
- QString version = attributes.value("version");
- if (!version.isEmpty() && version != "1.0") {
+ if (qName == QLatin1String("xbel")) {
+ QString version = attributes.value(versionAttribute());
+ if (!version.isEmpty() && version != QLatin1String("1.0")) {
errorStr = QObject::tr("The file is not an XBEL version 1.0 file.");
return false;
}
metXbelTag = true;
- } else if (qName == "folder") {
+ } else if (qName == QLatin1String("folder")) {
item = createChildItem(qName);
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setIcon(0, folderIcon);
item->setText(0, QObject::tr("Folder"));
- bool folded = (attributes.value("folded") != "no");
+ bool folded = (attributes.value(foldedAttribute()) != QLatin1String("no"));
treeWidget->setItemExpanded(item, !folded);
- } else if (qName == "bookmark") {
+ } else if (qName == QLatin1String("bookmark")) {
item = createChildItem(qName);
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setIcon(0, bookmarkIcon);
item->setText(0, QObject::tr("Unknown title"));
- item->setText(1, attributes.value("href"));
- } else if (qName == "separator") {
+ item->setText(1, attributes.value(hrefAttribute()));
+ } else if (qName == QLatin1String("separator")) {
item = createChildItem(qName);
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
item->setText(0, QString(30, 0xB7));
@@ -111,11 +115,11 @@ bool XbelHandler::endElement(const QString & /* namespaceURI */,
const QString & /* localName */,
const QString &qName)
{
- if (qName == "title") {
+ if (qName == QLatin1String("title")) {
if (item)
item->setText(0, currentText);
- } else if (qName == "folder" || qName == "bookmark"
- || qName == "separator") {
+ } else if (qName == QLatin1String("folder") || qName == QLatin1String("bookmark")
+ || qName == QLatin1String("separator")) {
item = item->parent();
}
return true;
diff --git a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
index 0720e3eadd..ad093c2098 100644
--- a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
+++ b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
@@ -167,7 +167,7 @@
add them to the \c fileMenu and \c helpMenu. The connections are as shown
below:
- \snippet streambookmarks/mainwindow.cpp 4
+ \snippet streambookmarks/mainwindow.cpp 5
The \c createMenus() function creates the \c fileMenu and \c helpMenu
and adds the QAction objects to them in order to create the menu shown
diff --git a/examples/xml/streambookmarks/mainwindow.cpp b/examples/xml/streambookmarks/mainwindow.cpp
index 7c0fd8720d..c9a18fa3c4 100644
--- a/examples/xml/streambookmarks/mainwindow.cpp
+++ b/examples/xml/streambookmarks/mainwindow.cpp
@@ -63,18 +63,41 @@ MainWindow::MainWindow()
treeWidget = new QTreeWidget;
treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
treeWidget->setHeaderLabels(labels);
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(treeWidget, &QWidget::customContextMenuRequested,
+ this, &MainWindow::onCustomContextMenuRequested);
+#endif
setCentralWidget(treeWidget);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("QXmlStream Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
//! [0]
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
+{
+ const QTreeWidgetItem *item = treeWidget->itemAt(pos);
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos));
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
//! [1]
void MainWindow::open()
{
@@ -92,8 +115,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -101,8 +124,8 @@ void MainWindow::open()
if (!reader.read(&file)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Parse error in file %1:\n\n%2")
- .arg(fileName)
- .arg(reader.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ reader.errorString()));
} else {
statusBar()->showMessage(tr("File loaded"), 2000);
}
@@ -124,8 +147,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -144,41 +167,23 @@ void MainWindow::about()
}
//! [3]
-//! [4]
-void MainWindow::createActions()
+//! [5]
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-//! [4]
-
-//! [5]
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
//! [5]
diff --git a/examples/xml/streambookmarks/mainwindow.h b/examples/xml/streambookmarks/mainwindow.h
index 2b6feeb26f..fbdc1e0c62 100644
--- a/examples/xml/streambookmarks/mainwindow.h
+++ b/examples/xml/streambookmarks/mainwindow.h
@@ -69,20 +69,13 @@ public slots:
void open();
void saveAs();
void about();
-
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void onCustomContextMenuRequested(const QPoint &pos);
+#endif
private:
- void createActions();
void createMenus();
QTreeWidget *treeWidget;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
//! [0]
diff --git a/examples/xml/streambookmarks/streambookmarks.pro b/examples/xml/streambookmarks/streambookmarks.pro
index 62aac0eef3..8c2fc3fa19 100644
--- a/examples/xml/streambookmarks/streambookmarks.pro
+++ b/examples/xml/streambookmarks/streambookmarks.pro
@@ -6,6 +6,7 @@ SOURCES = main.cpp \
xbelreader.cpp \
xbelwriter.cpp
QT += xml widgets
+requires(qtConfig(filedialog))
EXAMPLE_FILES = frank.xbel jennifer.xbel
diff --git a/examples/xml/streambookmarks/xbelreader.cpp b/examples/xml/streambookmarks/xbelreader.cpp
index 53d6b94ba0..099985d91e 100644
--- a/examples/xml/streambookmarks/xbelreader.cpp
+++ b/examples/xml/streambookmarks/xbelreader.cpp
@@ -72,10 +72,12 @@ bool XbelReader::read(QIODevice *device)
xml.setDevice(device);
if (xml.readNextStartElement()) {
- if (xml.name() == "xbel" && xml.attributes().value("version") == "1.0")
+ if (xml.name() == QLatin1String("xbel")
+ && xml.attributes().value(versionAttribute()) == QLatin1String("1.0")) {
readXBEL();
- else
+ } else {
xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
+ }
}
return !xml.error();
@@ -95,14 +97,14 @@ QString XbelReader::errorString() const
//! [3]
void XbelReader::readXBEL()
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "xbel");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("xbel"));
while (xml.readNextStartElement()) {
- if (xml.name() == "folder")
+ if (xml.name() == QLatin1String("folder"))
readFolder(0);
- else if (xml.name() == "bookmark")
+ else if (xml.name() == QLatin1String("bookmark"))
readBookmark(0);
- else if (xml.name() == "separator")
+ else if (xml.name() == QLatin1String("separator"))
readSeparator(0);
else
xml.skipCurrentElement();
@@ -113,7 +115,7 @@ void XbelReader::readXBEL()
//! [4]
void XbelReader::readTitle(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "title");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("title"));
QString title = xml.readElementText();
item->setText(0, title);
@@ -123,7 +125,7 @@ void XbelReader::readTitle(QTreeWidgetItem *item)
//! [5]
void XbelReader::readSeparator(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "separator");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("separator"));
QTreeWidgetItem *separator = createChildItem(item);
separator->setFlags(item->flags() & ~Qt::ItemIsSelectable);
@@ -134,20 +136,20 @@ void XbelReader::readSeparator(QTreeWidgetItem *item)
void XbelReader::readFolder(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "folder");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("folder"));
QTreeWidgetItem *folder = createChildItem(item);
- bool folded = (xml.attributes().value("folded") != "no");
+ bool folded = (xml.attributes().value(foldedAttribute()) != QLatin1String("no"));
treeWidget->setItemExpanded(folder, !folded);
while (xml.readNextStartElement()) {
- if (xml.name() == "title")
+ if (xml.name() == QLatin1String("title"))
readTitle(folder);
- else if (xml.name() == "folder")
+ else if (xml.name() == QLatin1String("folder"))
readFolder(folder);
- else if (xml.name() == "bookmark")
+ else if (xml.name() == QLatin1String("bookmark"))
readBookmark(folder);
- else if (xml.name() == "separator")
+ else if (xml.name() == QLatin1String("separator"))
readSeparator(folder);
else
xml.skipCurrentElement();
@@ -156,16 +158,16 @@ void XbelReader::readFolder(QTreeWidgetItem *item)
void XbelReader::readBookmark(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "bookmark");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("bookmark"));
QTreeWidgetItem *bookmark = createChildItem(item);
bookmark->setFlags(bookmark->flags() | Qt::ItemIsEditable);
bookmark->setIcon(0, bookmarkIcon);
bookmark->setText(0, QObject::tr("Unknown title"));
- bookmark->setText(1, xml.attributes().value("href").toString());
+ bookmark->setText(1, xml.attributes().value(hrefAttribute()).toString());
while (xml.readNextStartElement()) {
- if (xml.name() == "title")
+ if (xml.name() == QLatin1String("title"))
readTitle(bookmark);
else
xml.skipCurrentElement();
diff --git a/examples/xml/streambookmarks/xbelreader.h b/examples/xml/streambookmarks/xbelreader.h
index 3175441ddd..fd486a430f 100644
--- a/examples/xml/streambookmarks/xbelreader.h
+++ b/examples/xml/streambookmarks/xbelreader.h
@@ -71,6 +71,10 @@ public:
QString errorString() const;
+ static inline QString versionAttribute() { return QStringLiteral("version"); }
+ static inline QString hrefAttribute() { return QStringLiteral("href"); }
+ static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
private:
//! [2]
void readXBEL();
diff --git a/examples/xml/streambookmarks/xbelwriter.cpp b/examples/xml/streambookmarks/xbelwriter.cpp
index fdf2e1095e..2959680678 100644
--- a/examples/xml/streambookmarks/xbelwriter.cpp
+++ b/examples/xml/streambookmarks/xbelwriter.cpp
@@ -51,9 +51,14 @@
#include <QtWidgets>
#include "xbelwriter.h"
+#include "xbelreader.h"
+
+static inline QString yesValue() { return QStringLiteral("yes"); }
+static inline QString noValue() { return QStringLiteral("no"); }
+static inline QString titleElement() { return QStringLiteral("title"); }
//! [0]
-XbelWriter::XbelWriter(QTreeWidget *treeWidget)
+XbelWriter::XbelWriter(const QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
xml.setAutoFormatting(true);
@@ -66,9 +71,9 @@ bool XbelWriter::writeFile(QIODevice *device)
xml.setDevice(device);
xml.writeStartDocument();
- xml.writeDTD("<!DOCTYPE xbel>");
- xml.writeStartElement("xbel");
- xml.writeAttribute("version", "1.0");
+ xml.writeDTD(QStringLiteral("<!DOCTYPE xbel>"));
+ xml.writeStartElement(QStringLiteral("xbel"));
+ xml.writeAttribute(XbelReader::versionAttribute(), QStringLiteral("1.0"));
for (int i = 0; i < treeWidget->topLevelItemCount(); ++i)
writeItem(treeWidget->topLevelItem(i));
@@ -78,24 +83,24 @@ bool XbelWriter::writeFile(QIODevice *device)
//! [1]
//! [2]
-void XbelWriter::writeItem(QTreeWidgetItem *item)
+void XbelWriter::writeItem(const QTreeWidgetItem *item)
{
QString tagName = item->data(0, Qt::UserRole).toString();
- if (tagName == "folder") {
+ if (tagName == QLatin1String("folder")) {
bool folded = !treeWidget->isItemExpanded(item);
xml.writeStartElement(tagName);
- xml.writeAttribute("folded", folded ? "yes" : "no");
- xml.writeTextElement("title", item->text(0));
+ xml.writeAttribute(XbelReader::foldedAttribute(), folded ? yesValue() : noValue());
+ xml.writeTextElement(titleElement(), item->text(0));
for (int i = 0; i < item->childCount(); ++i)
writeItem(item->child(i));
xml.writeEndElement();
- } else if (tagName == "bookmark") {
+ } else if (tagName == QLatin1String("bookmark")) {
xml.writeStartElement(tagName);
if (!item->text(1).isEmpty())
- xml.writeAttribute("href", item->text(1));
- xml.writeTextElement("title", item->text(0));
+ xml.writeAttribute(XbelReader::hrefAttribute(), item->text(1));
+ xml.writeTextElement(titleElement(), item->text(0));
xml.writeEndElement();
- } else if (tagName == "separator") {
+ } else if (tagName == QLatin1String("separator")) {
xml.writeEmptyElement(tagName);
}
}
diff --git a/examples/xml/streambookmarks/xbelwriter.h b/examples/xml/streambookmarks/xbelwriter.h
index b15bf60e31..465d8f0dc4 100644
--- a/examples/xml/streambookmarks/xbelwriter.h
+++ b/examples/xml/streambookmarks/xbelwriter.h
@@ -62,13 +62,13 @@ QT_END_NAMESPACE
class XbelWriter
{
public:
- XbelWriter(QTreeWidget *treeWidget);
+ explicit XbelWriter(const QTreeWidget *treeWidget);
bool writeFile(QIODevice *device);
private:
- void writeItem(QTreeWidgetItem *item);
+ void writeItem(const QTreeWidgetItem *item);
QXmlStreamWriter xml;
- QTreeWidget *treeWidget;
+ const QTreeWidget *treeWidget;
};
//! [0]